1//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Tests for the correct import of AST nodes from one AST context to another.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/ASTMatchers/ASTMatchers.h"
14#include "llvm/ADT/StringMap.h"
15#include "llvm/Support/SmallVectorMemoryBuffer.h"
16
17#include "clang/AST/DeclContextInternals.h"
18#include "gtest/gtest.h"
19
20#include "ASTImporterFixtures.h"
21
22namespace clang {
23namespace ast_matchers {
24
25using internal::Matcher;
26using internal::BindableMatcher;
27using llvm::StringMap;
28
29static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
30 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
31 return cast<RecordType>(Ty)->getDecl();
32}
33
34struct ImportExpr : TestImportBase {};
35struct ImportType : TestImportBase {};
36struct ImportDecl : TestImportBase {};
37struct ImportFixedPointExpr : ImportExpr {};
38
39struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
40
41TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
42 Decl *FromTU = getTuDecl("void f();", Lang_CXX03);
43 auto Pattern = functionDecl(hasName("f"));
44 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
45
46 auto Redecls = getCanonicalForwardRedeclChain(D0);
47 ASSERT_EQ(Redecls.size(), 1u);
48 EXPECT_EQ(D0, Redecls[0]);
49}
50
51TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
52 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX03);
53 auto Pattern = functionDecl(hasName("f"));
54 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
55 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
56 FunctionDecl *D1 = D2->getPreviousDecl();
57
58 auto Redecls = getCanonicalForwardRedeclChain(D0);
59 ASSERT_EQ(Redecls.size(), 3u);
60 EXPECT_EQ(D0, Redecls[0]);
61 EXPECT_EQ(D1, Redecls[1]);
62 EXPECT_EQ(D2, Redecls[2]);
63}
64
65TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
66 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX03);
67 auto Pattern = functionDecl(hasName("f"));
68 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
69 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
70 FunctionDecl *D1 = D2->getPreviousDecl();
71
72 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
73 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
74 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
75
76 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
77 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
78}
79
80namespace {
81struct RedirectingImporter : public ASTImporter {
82 using ASTImporter::ASTImporter;
83
84protected:
85 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
86 auto *ND = dyn_cast<NamedDecl>(FromD);
87 if (!ND || ND->getName() != "shouldNotBeImported")
88 return ASTImporter::ImportImpl(FromD);
89 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {
90 if (auto *ND = dyn_cast<NamedDecl>(D))
91 if (ND->getName() == "realDecl") {
92 RegisterImportedDecl(FromD, ND);
93 return ND;
94 }
95 }
96 return ASTImporter::ImportImpl(FromD);
97 }
98};
99
100} // namespace
101
102struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
103 RedirectingImporterTest() {
104 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
105 ASTContext &FromContext, FileManager &FromFileManager,
106 bool MinimalImport,
107 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
108 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
109 FromFileManager, MinimalImport,
110 SharedState);
111 };
112 }
113};
114
115// Test that an ASTImporter subclass can intercept an import call.
116TEST_P(RedirectingImporterTest, InterceptImport) {
117 Decl *From, *To;
118 std::tie(From, To) =
119 getImportedDecl("class shouldNotBeImported {};", Lang_CXX03,
120 "class realDecl {};", Lang_CXX03, "shouldNotBeImported");
121 auto *Imported = cast<CXXRecordDecl>(To);
122 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
123
124 // Make sure our importer prevented the importing of the decl.
125 auto *ToTU = Imported->getTranslationUnitDecl();
126 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
127 unsigned count =
128 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
129 EXPECT_EQ(0U, count);
130}
131
132// Test that when we indirectly import a declaration the custom ASTImporter
133// is still intercepting the import.
134TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
135 Decl *From, *To;
136 std::tie(From, To) =
137 getImportedDecl("class shouldNotBeImported {};"
138 "class F { shouldNotBeImported f; };",
139 Lang_CXX03, "class realDecl {};", Lang_CXX03, "F");
140
141 // Make sure our ASTImporter prevented the importing of the decl.
142 auto *ToTU = To->getTranslationUnitDecl();
143 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
144 unsigned count =
145 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
146 EXPECT_EQ(0U, count);
147}
148
149struct ImportPath : ASTImporterOptionSpecificTestBase {
150 Decl *FromTU;
151 FunctionDecl *D0, *D1, *D2;
152 ImportPath() {
153 FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX03);
154 auto Pattern = functionDecl(hasName("f"));
155 D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
156 D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
157 D1 = D2->getPreviousDecl();
158 }
159};
160
161TEST_P(ImportPath, Push) {
162 ASTImporter::ImportPathTy path;
163 path.push(D0);
164 EXPECT_FALSE(path.hasCycleAtBack());
165}
166
167TEST_P(ImportPath, SmallCycle) {
168 ASTImporter::ImportPathTy path;
169 path.push(D0);
170 path.push(D0);
171 EXPECT_TRUE(path.hasCycleAtBack());
172 path.pop();
173 EXPECT_FALSE(path.hasCycleAtBack());
174 path.push(D0);
175 EXPECT_TRUE(path.hasCycleAtBack());
176}
177
178TEST_P(ImportPath, GetSmallCycle) {
179 ASTImporter::ImportPathTy path;
180 path.push(D0);
181 path.push(D0);
182 EXPECT_TRUE(path.hasCycleAtBack());
183 std::array<Decl* ,2> Res;
184 int i = 0;
185 for (Decl *Di : path.getCycleAtBack()) {
186 Res[i++] = Di;
187 }
188 ASSERT_EQ(i, 2);
189 EXPECT_EQ(Res[0], D0);
190 EXPECT_EQ(Res[1], D0);
191}
192
193TEST_P(ImportPath, GetCycle) {
194 ASTImporter::ImportPathTy path;
195 path.push(D0);
196 path.push(D1);
197 path.push(D2);
198 path.push(D0);
199 EXPECT_TRUE(path.hasCycleAtBack());
200 std::array<Decl* ,4> Res;
201 int i = 0;
202 for (Decl *Di : path.getCycleAtBack()) {
203 Res[i++] = Di;
204 }
205 ASSERT_EQ(i, 4);
206 EXPECT_EQ(Res[0], D0);
207 EXPECT_EQ(Res[1], D2);
208 EXPECT_EQ(Res[2], D1);
209 EXPECT_EQ(Res[3], D0);
210}
211
212TEST_P(ImportPath, CycleAfterCycle) {
213 ASTImporter::ImportPathTy path;
214 path.push(D0);
215 path.push(D1);
216 path.push(D0);
217 path.push(D1);
218 path.push(D2);
219 path.push(D0);
220 EXPECT_TRUE(path.hasCycleAtBack());
221 std::array<Decl* ,4> Res;
222 int i = 0;
223 for (Decl *Di : path.getCycleAtBack()) {
224 Res[i++] = Di;
225 }
226 ASSERT_EQ(i, 4);
227 EXPECT_EQ(Res[0], D0);
228 EXPECT_EQ(Res[1], D2);
229 EXPECT_EQ(Res[2], D1);
230 EXPECT_EQ(Res[3], D0);
231
232 path.pop();
233 path.pop();
234 path.pop();
235 EXPECT_TRUE(path.hasCycleAtBack());
236 i = 0;
237 for (Decl *Di : path.getCycleAtBack()) {
238 Res[i++] = Di;
239 }
240 ASSERT_EQ(i, 3);
241 EXPECT_EQ(Res[0], D0);
242 EXPECT_EQ(Res[1], D1);
243 EXPECT_EQ(Res[2], D0);
244
245 path.pop();
246 EXPECT_FALSE(path.hasCycleAtBack());
247}
248
249TEST_P(ImportExpr, ImportStringLiteral) {
250 MatchVerifier<Decl> Verifier;
251 testImport("void declToImport() { (void)\"foo\"; }", Lang_CXX03, "",
252 Lang_CXX03, Verifier,
253 functionDecl(hasDescendant(
254 stringLiteral(hasType(asString("const char [4]"))))));
255 testImport("void declToImport() { (void)L\"foo\"; }", Lang_CXX03, "",
256 Lang_CXX03, Verifier,
257 functionDecl(hasDescendant(
258 stringLiteral(hasType(asString("const wchar_t [4]"))))));
259 testImport("void declToImport() { (void) \"foo\" \"bar\"; }", Lang_CXX03, "",
260 Lang_CXX03, Verifier,
261 functionDecl(hasDescendant(
262 stringLiteral(hasType(asString("const char [7]"))))));
263}
264
265TEST_P(ImportExpr, ImportChooseExpr) {
266 MatchVerifier<Decl> Verifier;
267
268 // This case tests C code that is not condition-dependent and has a true
269 // condition.
270 testImport("void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
271 Lang_C99, "", Lang_C99, Verifier,
272 functionDecl(hasDescendant(chooseExpr())));
273}
274
275TEST_P(ImportExpr, ImportGNUNullExpr) {
276 MatchVerifier<Decl> Verifier;
277 testImport("void declToImport() { (void)__null; }", Lang_CXX03, "",
278 Lang_CXX03, Verifier,
279 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
280}
281
282TEST_P(ImportExpr, ImportGenericSelectionExpr) {
283 MatchVerifier<Decl> Verifier;
284
285 testImport(
286 "void declToImport() { int x; (void)_Generic(x, int: 0, float: 1); }",
287 Lang_C99, "", Lang_C99, Verifier,
288 functionDecl(hasDescendant(genericSelectionExpr())));
289}
290
291TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
292 MatchVerifier<Decl> Verifier;
293 testImport(
294 "void declToImport() { (void)nullptr; }",
295 Lang_CXX11, "", Lang_CXX11, Verifier,
296 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
297}
298
299
300TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
301 MatchVerifier<Decl> Verifier;
302 testImport("void declToImport() { (void)1.0; }", Lang_C99, "", Lang_C99,
303 Verifier,
304 functionDecl(hasDescendant(
305 floatLiteral(equals(1.0), hasType(asString("double"))))));
306 testImport("void declToImport() { (void)1.0e-5f; }", Lang_C99, "", Lang_C99,
307 Verifier,
308 functionDecl(hasDescendant(
309 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
310}
311
312TEST_P(ImportFixedPointExpr, ImportFixedPointerLiteralExpr) {
313 MatchVerifier<Decl> Verifier;
314 testImport("void declToImport() { (void)1.0k; }", Lang_C99, "", Lang_C99,
315 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));
316 testImport("void declToImport() { (void)0.75r; }", Lang_C99, "", Lang_C99,
317 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));
318}
319
320TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
321 MatchVerifier<Decl> Verifier;
322 testImport(
323 "void declToImport() { (void)1.0i; }",
324 Lang_CXX14, "", Lang_CXX14, Verifier,
325 functionDecl(hasDescendant(imaginaryLiteral())));
326}
327
328TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
329 MatchVerifier<Decl> Verifier;
330 testImport("void declToImport() {"
331 " struct s { int x; long y; unsigned z; }; "
332 " (void)(struct s){ 42, 0L, 1U }; }",
333 Lang_CXX03, "", Lang_CXX03, Verifier,
334 functionDecl(hasDescendant(compoundLiteralExpr(
335 hasType(asString("struct s")),
336 has(initListExpr(
337 hasType(asString("struct s")),
338 has(integerLiteral(equals(42), hasType(asString("int")))),
339 has(integerLiteral(equals(0), hasType(asString("long")))),
340 has(integerLiteral(
341 equals(1), hasType(asString("unsigned int"))))))))));
342}
343
344TEST_P(ImportExpr, ImportCXXThisExpr) {
345 MatchVerifier<Decl> Verifier;
346 testImport("class declToImport { void f() { (void)this; } };", Lang_CXX03, "",
347 Lang_CXX03, Verifier,
348 cxxRecordDecl(hasMethod(hasDescendant(
349 cxxThisExpr(hasType(asString("class declToImport *")))))));
350}
351
352TEST_P(ImportExpr, ImportAtomicExpr) {
353 MatchVerifier<Decl> Verifier;
354 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
355 Lang_C99, "", Lang_C99, Verifier,
356 functionDecl(hasDescendant(atomicExpr(
357 has(ignoringParenImpCasts(
358 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
359 hasType(asString("int *"))))),
360 has(integerLiteral(equals(1), hasType(asString("int"))))))));
361}
362
363TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
364 MatchVerifier<Decl> Verifier;
365 testImport("void declToImport() { loop: goto loop; (void)&&loop; }", Lang_C99,
366 "", Lang_C99, Verifier,
367 functionDecl(hasDescendant(labelStmt(
368 hasDeclaration(labelDecl(hasName("loop"))))),
369 hasDescendant(addrLabelExpr(
370 hasDeclaration(labelDecl(hasName("loop")))))));
371}
372
373AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
374 internal::Matcher<NamedDecl>, InnerMatcher) {
375 const NamedDecl *Template = Node.getTemplatedDecl();
376 return Template && InnerMatcher.matches(*Template, Finder, Builder);
377}
378
379TEST_P(ImportExpr, ImportParenListExpr) {
380 MatchVerifier<Decl> Verifier;
381 testImport(
382 "template<typename T> class dummy { void f() { dummy X(*this); } };"
383 "typedef dummy<int> declToImport;"
384 "template class dummy<int>;",
385 Lang_CXX03, "", Lang_CXX03, Verifier,
386 typedefDecl(hasType(templateSpecializationType(
387 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
388 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
389 hasName("f"),
390 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
391 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
392 hasOperatorName("*"),
393 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
394}
395
396TEST_P(ImportExpr, ImportSwitch) {
397 MatchVerifier<Decl> Verifier;
398 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
399 Lang_C99, "", Lang_C99, Verifier,
400 functionDecl(hasDescendant(
401 switchStmt(has(compoundStmt(has(caseStmt())))))));
402}
403
404TEST_P(ImportExpr, ImportStmtExpr) {
405 MatchVerifier<Decl> Verifier;
406 testImport(
407 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
408 Lang_C99, "", Lang_C99, Verifier,
409 traverse(TK_AsIs,
410 functionDecl(hasDescendant(varDecl(
411 hasName("C"), hasType(asString("int")),
412 hasInitializer(stmtExpr(
413 hasAnySubstatement(declStmt(hasSingleDecl(varDecl(
414 hasName("X"), hasType(asString("int")),
415 hasInitializer(integerLiteral(equals(4))))))),
416 hasDescendant(implicitCastExpr()))))))));
417}
418
419TEST_P(ImportExpr, ImportConditionalOperator) {
420 MatchVerifier<Decl> Verifier;
421 testImport("void declToImport() { (void)(true ? 1 : -5); }", Lang_CXX03, "",
422 Lang_CXX03, Verifier,
423 functionDecl(hasDescendant(conditionalOperator(
424 hasCondition(cxxBoolLiteral(equals(true))),
425 hasTrueExpression(integerLiteral(equals(1))),
426 hasFalseExpression(unaryOperator(
427 hasUnaryOperand(integerLiteral(equals(5)))))))));
428}
429
430TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
431 MatchVerifier<Decl> Verifier;
432 testImport(
433 "void declToImport() { (void)(1 ?: -5); }", Lang_CXX03, "", Lang_CXX03,
434 Verifier,
435 traverse(TK_AsIs,
436 functionDecl(hasDescendant(binaryConditionalOperator(
437 hasCondition(implicitCastExpr(
438 hasSourceExpression(opaqueValueExpr(
439 hasSourceExpression(integerLiteral(equals(1))))),
440 hasType(booleanType()))),
441 hasTrueExpression(opaqueValueExpr(
442 hasSourceExpression(integerLiteral(equals(1))))),
443 hasFalseExpression(unaryOperator(
444 hasOperatorName("-"),
445 hasUnaryOperand(integerLiteral(equals(5))))))))));
446}
447
448TEST_P(ImportExpr, ImportDesignatedInitExpr) {
449 MatchVerifier<Decl> Verifier;
450 testImport(
451 "void declToImport() {"
452 " struct point { double x; double y; };"
453 " struct point ptarray[10] = "
454 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
455 Lang_C99, "", Lang_C99, Verifier,
456 functionDecl(hasDescendant(initListExpr(
457 has(designatedInitExpr(designatorCountIs(2),
458 hasDescendant(floatLiteral(equals(1.0))),
459 hasDescendant(integerLiteral(equals(2))))),
460 has(designatedInitExpr(designatorCountIs(2),
461 hasDescendant(floatLiteral(equals(2.0))),
462 hasDescendant(integerLiteral(equals(2))))),
463 has(designatedInitExpr(designatorCountIs(2),
464 hasDescendant(floatLiteral(equals(1.0))),
465 hasDescendant(integerLiteral(equals(0)))))))));
466}
467
468TEST_P(ImportExpr, ImportPredefinedExpr) {
469 MatchVerifier<Decl> Verifier;
470 // __func__ expands as StringLiteral("declToImport")
471 testImport("void declToImport() { (void)__func__; }", Lang_CXX03, "",
472 Lang_CXX03, Verifier,
473 functionDecl(hasDescendant(predefinedExpr(
474 hasType(asString("const char [13]")),
475 has(stringLiteral(hasType(asString("const char [13]"))))))));
476}
477
478TEST_P(ImportExpr, ImportInitListExpr) {
479 MatchVerifier<Decl> Verifier;
480 testImport(
481 "void declToImport() {"
482 " struct point { double x; double y; };"
483 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
484 " [0].x = 1.0 }; }",
485 Lang_CXX03, "", Lang_CXX03, Verifier,
486 functionDecl(hasDescendant(initListExpr(
487 has(cxxConstructExpr(requiresZeroInitialization())),
488 has(initListExpr(
489 hasType(asString("struct point")), has(floatLiteral(equals(1.0))),
490 has(implicitValueInitExpr(hasType(asString("double")))))),
491 has(initListExpr(hasType(asString("struct point")),
492 has(floatLiteral(equals(2.0))),
493 has(floatLiteral(equals(1.0)))))))));
494}
495
496
497const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
498
499TEST_P(ImportExpr, ImportVAArgExpr) {
500 MatchVerifier<Decl> Verifier;
501 testImport("void declToImport(__builtin_va_list list, ...) {"
502 " (void)__builtin_va_arg(list, int); }",
503 Lang_CXX03, "", Lang_CXX03, Verifier,
504 functionDecl(hasDescendant(
505 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
506}
507
508TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
509 MatchVerifier<Decl> Verifier;
510 testImport(
511 "struct C {};"
512 "void declToImport() { C c = C(); }",
513 Lang_CXX03, "", Lang_CXX03, Verifier,
514 traverse(TK_AsIs,
515 functionDecl(hasDescendant(exprWithCleanups(has(cxxConstructExpr(
516 has(materializeTemporaryExpr(has(implicitCastExpr(
517 has(cxxTemporaryObjectExpr()))))))))))));
518}
519
520TEST_P(ImportType, ImportAtomicType) {
521 MatchVerifier<Decl> Verifier;
522 testImport(
523 "void declToImport() { typedef _Atomic(int) a_int; }",
524 Lang_CXX11, "", Lang_CXX11, Verifier,
525 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
526}
527
528TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
529 MatchVerifier<Decl> Verifier;
530 testImport("template <typename T> void declToImport() { };", Lang_CXX03, "",
531 Lang_CXX03, Verifier, functionTemplateDecl());
532}
533
534TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
535 MatchVerifier<Decl> Verifier;
536 testImport("template <typename T> struct C { T t; };"
537 "template <typename T> void declToImport() {"
538 " C<T> d;"
539 " (void)d.t;"
540 "}"
541 "void instantiate() { declToImport<int>(); }",
542 Lang_CXX03, "", Lang_CXX03, Verifier,
543 functionTemplateDecl(hasDescendant(
544 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
545 testImport("template <typename T> struct C { T t; };"
546 "template <typename T> void declToImport() {"
547 " C<T> d;"
548 " (void)(&d)->t;"
549 "}"
550 "void instantiate() { declToImport<int>(); }",
551 Lang_CXX03, "", Lang_CXX03, Verifier,
552 functionTemplateDecl(hasDescendant(
553 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
554}
555
556TEST_P(ImportType, ImportTypeAliasTemplate) {
557 MatchVerifier<Decl> Verifier;
558 testImport(
559 "template <int K>"
560 "struct dummy { static const int i = K; };"
561 "template <int K> using dummy2 = dummy<K>;"
562 "int declToImport() { return dummy2<3>::i; }",
563 Lang_CXX11, "", Lang_CXX11, Verifier,
564 traverse(TK_AsIs,
565 functionDecl(hasDescendant(implicitCastExpr(has(declRefExpr()))),
566 unless(hasAncestor(
567 translationUnitDecl(has(typeAliasDecl())))))));
568}
569
570const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
571 varTemplateSpecializationDecl;
572
573TEST_P(ImportDecl, ImportVarTemplate) {
574 MatchVerifier<Decl> Verifier;
575 testImport(
576 "template <typename T>"
577 "T pi = T(3.1415926535897932385L);"
578 "void declToImport() { (void)pi<int>; }",
579 Lang_CXX14, "", Lang_CXX14, Verifier,
580 functionDecl(
581 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
582 unless(hasAncestor(translationUnitDecl(has(varDecl(
583 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
584}
585
586TEST_P(ImportType, ImportPackExpansion) {
587 MatchVerifier<Decl> Verifier;
588 testImport("template <typename... Args>"
589 "struct dummy {"
590 " dummy(Args... args) {}"
591 " static const int i = 4;"
592 "};"
593 "int declToImport() { return dummy<int>::i; }",
594 Lang_CXX11, "", Lang_CXX11, Verifier,
595 traverse(TK_AsIs, functionDecl(hasDescendant(returnStmt(has(
596 implicitCastExpr(has(declRefExpr()))))))));
597}
598
599const internal::VariadicDynCastAllOfMatcher<Type,
600 DependentTemplateSpecializationType>
601 dependentTemplateSpecializationType;
602
603TEST_P(ImportType, ImportDependentTemplateSpecialization) {
604 MatchVerifier<Decl> Verifier;
605 testImport("template<typename T>"
606 "struct A;"
607 "template<typename T>"
608 "struct declToImport {"
609 " typename A<T>::template B<T> a;"
610 "};",
611 Lang_CXX03, "", Lang_CXX03, Verifier,
612 classTemplateDecl(has(cxxRecordDecl(has(
613 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
614}
615
616const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
617 sizeOfPackExpr;
618
619TEST_P(ImportExpr, ImportSizeOfPackExpr) {
620 MatchVerifier<Decl> Verifier;
621 testImport(
622 "template <typename... Ts>"
623 "void declToImport() {"
624 " const int i = sizeof...(Ts);"
625 "};"
626 "void g() { declToImport<int>(); }",
627 Lang_CXX11, "", Lang_CXX11, Verifier,
628 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
629 testImport(
630 "template <typename... Ts>"
631 "using X = int[sizeof...(Ts)];"
632 "template <typename... Us>"
633 "struct Y {"
634 " X<Us..., int, double, int, Us...> f;"
635 "};"
636 "Y<float, int> declToImport;",
637 Lang_CXX11, "", Lang_CXX11, Verifier,
638 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
639 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
640}
641
642const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFoldExpr> cxxFoldExpr;
643
644AST_MATCHER_P(CXXFoldExpr, hasOperator, BinaryOperatorKind, Op) {
645 return Node.getOperator() == Op;
646}
647AST_MATCHER(CXXFoldExpr, hasInit) { return Node.getInit(); }
648AST_MATCHER(CXXFoldExpr, isRightFold) { return Node.isRightFold(); }
649AST_MATCHER(CXXFoldExpr, isLeftFold) { return Node.isLeftFold(); }
650
651TEST_P(ImportExpr, ImportCXXFoldExpr) {
652 auto Match1 =
653 cxxFoldExpr(hasOperator(BO_Add), isLeftFold(), unless(hasInit()));
654 auto Match2 = cxxFoldExpr(hasOperator(BO_Sub), isLeftFold(), hasInit());
655 auto Match3 =
656 cxxFoldExpr(hasOperator(BO_Mul), isRightFold(), unless(hasInit()));
657 auto Match4 = cxxFoldExpr(hasOperator(BO_Div), isRightFold(), hasInit());
658
659 MatchVerifier<Decl> Verifier;
660 testImport("template <typename... Ts>"
661 "void declToImport(Ts... args) {"
662 " const int i1 = (... + args);"
663 " const int i2 = (1 - ... - args);"
664 " const int i3 = (args * ...);"
665 " const int i4 = (args / ... / 1);"
666 "};"
667 "void g() { declToImport(1, 2, 3, 4, 5); }",
668 Lang_CXX17, "", Lang_CXX17, Verifier,
669 functionTemplateDecl(hasDescendant(Match1), hasDescendant(Match2),
670 hasDescendant(Match3),
671 hasDescendant(Match4)));
672}
673
674/// \brief Matches __builtin_types_compatible_p:
675/// GNU extension to check equivalent types
676/// Given
677/// \code
678/// __builtin_types_compatible_p(int, int)
679/// \endcode
680// will generate TypeTraitExpr <...> 'int'
681const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
682
683TEST_P(ImportExpr, ImportTypeTraitExpr) {
684 MatchVerifier<Decl> Verifier;
685 testImport(
686 "void declToImport() { "
687 " (void)__builtin_types_compatible_p(int, int);"
688 "}",
689 Lang_C99, "", Lang_C99, Verifier,
690 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
691}
692
693const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
694
695TEST_P(ImportExpr, ImportCXXTypeidExpr) {
696 MatchVerifier<Decl> Verifier;
697 testImport(
698 "namespace std { class type_info {}; }"
699 "void declToImport() {"
700 " int x;"
701 " auto a = typeid(int); auto b = typeid(x);"
702 "}",
703 Lang_CXX11, "", Lang_CXX11, Verifier,
704 traverse(
705 TK_AsIs,
706 functionDecl(
707 hasDescendant(varDecl(hasName("a"), hasInitializer(hasDescendant(
708 cxxTypeidExpr())))),
709 hasDescendant(varDecl(hasName("b"), hasInitializer(hasDescendant(
710 cxxTypeidExpr())))))));
711}
712
713TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
714 MatchVerifier<Decl> Verifier;
715 testImport(
716 "template<typename T> struct declToImport {"
717 " void m() { (void)__is_pod(T); }"
718 "};"
719 "void f() { declToImport<int>().m(); }",
720 Lang_CXX11, "", Lang_CXX11, Verifier,
721 classTemplateDecl(has(cxxRecordDecl(has(
722 functionDecl(hasDescendant(
723 typeTraitExpr(hasType(booleanType())))))))));
724}
725
726TEST_P(ImportDecl, ImportRecordDeclInFunc) {
727 MatchVerifier<Decl> Verifier;
728 testImport("int declToImport() { "
729 " struct data_t {int a;int b;};"
730 " struct data_t d;"
731 " return 0;"
732 "}",
733 Lang_C99, "", Lang_C99, Verifier,
734 functionDecl(hasBody(compoundStmt(
735 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
736}
737
738TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
739 Decl *FromTU = getTuDecl("int declToImport() { "
740 " struct data_t {int a;int b;};"
741 " struct data_t d;"
742 " return 0;"
743 "}",
744 Lang_C99, "input.c");
745 auto *FromVar =
746 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
747 ASSERT_TRUE(FromVar);
748 auto ToType =
749 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C99);
750 EXPECT_FALSE(ToType.isNull());
751}
752
753TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
754 // This construct is not supported by ASTImporter.
755 Decl *FromTU = getTuDecl(
756 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
757 Lang_C99, "input.c");
758 auto *From = FirstDeclMatcher<FunctionDecl>().match(
759 FromTU, functionDecl(hasName("declToImport")));
760 ASSERT_TRUE(From);
761 auto *To = Import(From, Lang_C99);
762 EXPECT_EQ(To, nullptr);
763}
764
765TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
766 Decl *FromTU =
767 getTuDecl("#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
768 "int declToImport(){ return NONAME_SIZEOF(int); }",
769 Lang_C99, "input.c");
770 auto *From = FirstDeclMatcher<FunctionDecl>().match(
771 FromTU, functionDecl(hasName("declToImport")));
772 ASSERT_TRUE(From);
773 auto *To = Import(From, Lang_C99);
774 ASSERT_TRUE(To);
775 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
776 To, functionDecl(hasName("declToImport"),
777 hasDescendant(unaryExprOrTypeTraitExpr()))));
778}
779
780TEST_P(ASTImporterOptionSpecificTestBase,
781 ImportRecordDeclInFuncParamsFromMacro) {
782 // This construct is not supported by ASTImporter.
783 Decl *FromTU =
784 getTuDecl("#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
785 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
786 Lang_C99, "input.c");
787 auto *From = FirstDeclMatcher<FunctionDecl>().match(
788 FromTU, functionDecl(hasName("declToImport")));
789 ASSERT_TRUE(From);
790 auto *To = Import(From, Lang_C99);
791 EXPECT_EQ(To, nullptr);
792}
793
794const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
795 cxxPseudoDestructorExpr;
796
797TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
798 MatchVerifier<Decl> Verifier;
799 testImport(
800 "typedef int T;"
801 "void declToImport(int *p) {"
802 " T t;"
803 " p->T::~T();"
804 "}",
805 Lang_CXX03, "", Lang_CXX03, Verifier,
806 functionDecl(hasDescendant(callExpr(has(cxxPseudoDestructorExpr())))));
807}
808
809TEST_P(ImportDecl, ImportUsingDecl) {
810 MatchVerifier<Decl> Verifier;
811 testImport("namespace foo { int bar; }"
812 "void declToImport() { using foo::bar; }",
813 Lang_CXX03, "", Lang_CXX03, Verifier,
814 functionDecl(hasDescendant(usingDecl())));
815}
816
817/// \brief Matches shadow declarations introduced into a scope by a
818/// (resolved) using declaration.
819///
820/// Given
821/// \code
822/// namespace n { int f; }
823/// namespace declToImport { using n::f; }
824/// \endcode
825/// usingShadowDecl()
826/// matches \code f \endcode
827const internal::VariadicDynCastAllOfMatcher<Decl,
828 UsingShadowDecl> usingShadowDecl;
829
830TEST_P(ImportDecl, ImportUsingShadowDecl) {
831 MatchVerifier<Decl> Verifier;
832 testImport("namespace foo { int bar; }"
833 "namespace declToImport { using foo::bar; }",
834 Lang_CXX03, "", Lang_CXX03, Verifier,
835 namespaceDecl(has(usingShadowDecl())));
836}
837
838TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
839 MatchVerifier<Decl> Verifier;
840 testImport("template<typename T> int foo();"
841 "template <typename T> void declToImport() {"
842 " (void)::foo<T>;"
843 " (void)::template foo<T>;"
844 "}"
845 "void instantiate() { declToImport<int>(); }",
846 Lang_CXX03, "", Lang_CXX03, Verifier,
847 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
848}
849
850TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
851 MatchVerifier<Decl> Verifier;
852 testImport("template <typename T> struct C { T t; };"
853 "template <typename T> void declToImport() {"
854 " C<T> d;"
855 " d.t = T();"
856 "}"
857 "void instantiate() { declToImport<int>(); }",
858 Lang_CXX03, "", Lang_CXX03, Verifier,
859 functionTemplateDecl(hasDescendant(
860 binaryOperator(has(cxxUnresolvedConstructExpr())))));
861 testImport("template <typename T> struct C { T t; };"
862 "template <typename T> void declToImport() {"
863 " C<T> d;"
864 " (&d)->t = T();"
865 "}"
866 "void instantiate() { declToImport<int>(); }",
867 Lang_CXX03, "", Lang_CXX03, Verifier,
868 functionTemplateDecl(hasDescendant(
869 binaryOperator(has(cxxUnresolvedConstructExpr())))));
870}
871
872/// Check that function "declToImport()" (which is the templated function
873/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
874/// Same for class template declarations.
875TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
876 MatchVerifier<Decl> Verifier;
877 testImport("template <typename T> void declToImport() { T a = 1; }"
878 "void instantiate() { declToImport<int>(); }",
879 Lang_CXX03, "", Lang_CXX03, Verifier,
880 functionTemplateDecl(hasAncestor(translationUnitDecl(
881 unless(has(functionDecl(hasName("declToImport"))))))));
882 testImport("template <typename T> struct declToImport { T t; };"
883 "void instantiate() { declToImport<int>(); }",
884 Lang_CXX03, "", Lang_CXX03, Verifier,
885 classTemplateDecl(hasAncestor(translationUnitDecl(
886 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
887}
888
889TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
890 MatchVerifier<Decl> Verifier;
891 auto Code =
892 R"s(
893 struct declToImport {
894 template <typename T0> struct X;
895 template <typename T0> struct X<T0 *> {};
896 };
897 )s";
898 testImport(Code, Lang_CXX03, "", Lang_CXX03, Verifier,
899 recordDecl(has(classTemplateDecl()),
900 has(classTemplateSpecializationDecl())));
901}
902
903TEST_P(ImportExpr, CXXOperatorCallExpr) {
904 MatchVerifier<Decl> Verifier;
905 testImport(
906 "class declToImport {"
907 " void f() { *this = declToImport(); }"
908 "};",
909 Lang_CXX03, "", Lang_CXX03, Verifier,
910 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(cxxOperatorCallExpr())))));
911}
912
913TEST_P(ImportExpr, DependentSizedArrayType) {
914 MatchVerifier<Decl> Verifier;
915 testImport("template<typename T, int Size> class declToImport {"
916 " T data[Size];"
917 "};",
918 Lang_CXX03, "", Lang_CXX03, Verifier,
919 classTemplateDecl(has(cxxRecordDecl(
920 has(fieldDecl(hasType(dependentSizedArrayType())))))));
921}
922
923TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclNoDefaultArg) {
924 Decl *FromTU = getTuDecl("template<typename T> struct X {};", Lang_CXX03);
925 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
926 FromTU, templateTypeParmDecl(hasName("T")));
927 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);
928 ASSERT_FALSE(To->hasDefaultArgument());
929}
930
931TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclDefaultArg) {
932 Decl *FromTU =
933 getTuDecl("template<typename T = int> struct X {};", Lang_CXX03);
934 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
935 FromTU, templateTypeParmDecl(hasName("T")));
936 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);
937 ASSERT_TRUE(To->hasDefaultArgument());
938 QualType ToArg = To->getDefaultArgument();
939 ASSERT_EQ(ToArg, QualType(To->getASTContext().IntTy));
940}
941
942TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
943 Decl *FromTU =
944 getTuDecl("class A { public: static int X; }; void f() { (void)A::X; }",
945 Lang_CXX03);
946 auto From = FirstDeclMatcher<FunctionDecl>().match(
947 FromTU, functionDecl(hasName("f")));
948 ASSERT_TRUE(From);
949 ASSERT_TRUE(
950 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
951 ->getSubExpr()
952 ->getBeginLoc()
953 .isValid());
954 FunctionDecl *To = Import(From, Lang_CXX03);
955 ASSERT_TRUE(To);
956 ASSERT_TRUE(
957 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
958 ->getSubExpr()
959 ->getBeginLoc()
960 .isValid());
961}
962
963TEST_P(ASTImporterOptionSpecificTestBase,
964 TemplateTemplateParmDeclNoDefaultArg) {
965 Decl *FromTU = getTuDecl(R"(
966 template<template<typename> typename TT> struct Y {};
967 )",
968 Lang_CXX17);
969 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
970 FromTU, templateTemplateParmDecl(hasName("TT")));
971 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);
972 ASSERT_FALSE(To->hasDefaultArgument());
973}
974
975TEST_P(ASTImporterOptionSpecificTestBase, TemplateTemplateParmDeclDefaultArg) {
976 Decl *FromTU = getTuDecl(R"(
977 template<typename T> struct X {};
978 template<template<typename> typename TT = X> struct Y {};
979 )",
980 Lang_CXX17);
981 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
982 FromTU, templateTemplateParmDecl(hasName("TT")));
983 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);
984 ASSERT_TRUE(To->hasDefaultArgument());
985 const TemplateArgument &ToDefaultArg = To->getDefaultArgument().getArgument();
986 ASSERT_TRUE(To->isTemplateDecl());
987 TemplateDecl *ToTemplate = ToDefaultArg.getAsTemplate().getAsTemplateDecl();
988
989 // Find the default argument template 'X' in the AST and compare it against
990 // the default argument we got.
991 auto ToExpectedDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
992 To->getTranslationUnitDecl(), classTemplateDecl(hasName("X")));
993 ASSERT_EQ(ToTemplate, ToExpectedDecl);
994}
995
996TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclNoDefaultArg) {
997 Decl *FromTU = getTuDecl("template<int N> struct X {};", Lang_CXX03);
998 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
999 FromTU, nonTypeTemplateParmDecl(hasName("N")));
1000 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);
1001 ASSERT_FALSE(To->hasDefaultArgument());
1002}
1003
1004TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) {
1005 Decl *FromTU = getTuDecl("template<int S = 1> struct X {};", Lang_CXX03);
1006 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
1007 FromTU, nonTypeTemplateParmDecl(hasName("S")));
1008 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);
1009 ASSERT_TRUE(To->hasDefaultArgument());
1010 Stmt *ToArg = To->getDefaultArgument();
1011 ASSERT_TRUE(isa<ConstantExpr>(ToArg));
1012 ToArg = *ToArg->child_begin();
1013 ASSERT_TRUE(isa<IntegerLiteral>(ToArg));
1014 ASSERT_EQ(cast<IntegerLiteral>(ToArg)->getValue().getLimitedValue(), 1U);
1015}
1016
1017TEST_P(ASTImporterOptionSpecificTestBase,
1018 ImportOfTemplatedDeclOfClassTemplateDecl) {
1019 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03);
1020 auto From =
1021 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1022 ASSERT_TRUE(From);
1023 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX03));
1024 ASSERT_TRUE(To);
1025 Decl *ToTemplated = To->getTemplatedDecl();
1026 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);
1027 EXPECT_TRUE(ToTemplated1);
1028 EXPECT_EQ(ToTemplated1, ToTemplated);
1029}
1030
1031TEST_P(ASTImporterOptionSpecificTestBase,
1032 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
1033 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX03);
1034 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1035 FromTU, functionTemplateDecl());
1036 ASSERT_TRUE(From);
1037 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX03));
1038 ASSERT_TRUE(To);
1039 Decl *ToTemplated = To->getTemplatedDecl();
1040 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);
1041 EXPECT_TRUE(ToTemplated1);
1042 EXPECT_EQ(ToTemplated1, ToTemplated);
1043}
1044
1045TEST_P(ASTImporterOptionSpecificTestBase,
1046 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1047 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03);
1048 auto FromFT =
1049 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1050 ASSERT_TRUE(FromFT);
1051
1052 auto ToTemplated =
1053 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));
1054 EXPECT_TRUE(ToTemplated);
1055 auto ToTU = ToTemplated->getTranslationUnitDecl();
1056 auto ToFT =
1057 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1058 EXPECT_TRUE(ToFT);
1059}
1060
1061TEST_P(ASTImporterOptionSpecificTestBase,
1062 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
1063 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX03);
1064 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1065 FromTU, functionTemplateDecl());
1066 ASSERT_TRUE(FromFT);
1067
1068 auto ToTemplated =
1069 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));
1070 EXPECT_TRUE(ToTemplated);
1071 auto ToTU = ToTemplated->getTranslationUnitDecl();
1072 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1073 ToTU, functionTemplateDecl());
1074 EXPECT_TRUE(ToFT);
1075}
1076
1077TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
1078 auto Code =
1079 R"(
1080 namespace x {
1081 template<class X> struct S1{};
1082 template<class X> struct S2{};
1083 template<class X> struct S3{};
1084 }
1085 )";
1086 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
1087 auto FromNs =
1088 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1089 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX03));
1090 ASSERT_TRUE(ToNs);
1091 auto From =
1092 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1093 classTemplateDecl(
1094 hasName("S2")));
1095 auto To =
1096 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1097 classTemplateDecl(
1098 hasName("S2")));
1099 ASSERT_TRUE(From);
1100 ASSERT_TRUE(To);
1101 auto ToTemplated = To->getTemplatedDecl();
1102 auto ToTemplated1 =
1103 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX03));
1104 EXPECT_TRUE(ToTemplated1);
1105 ASSERT_EQ(ToTemplated1, ToTemplated);
1106}
1107
1108TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1109 // This tests the import of isConditionTrue directly to make sure the importer
1110 // gets it right.
1111 Decl *From, *To;
1112 std::tie(From, To) = getImportedDecl(
1113 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }", Lang_C99,
1114 "", Lang_C99);
1115
1116 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1117 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1118
1119 const ChooseExpr *FromChooseExpr =
1120 selectFirst<ChooseExpr>("choose", FromResults);
1121 ASSERT_TRUE(FromChooseExpr);
1122
1123 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1124 ASSERT_TRUE(ToChooseExpr);
1125
1126 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1127 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1128 ToChooseExpr->isConditionDependent());
1129}
1130
1131TEST_P(ASTImporterOptionSpecificTestBase, ImportGenericSelectionExpr) {
1132 Decl *From, *To;
1133 std::tie(From, To) = getImportedDecl(
1134 R"(
1135 int declToImport() {
1136 int x;
1137 return _Generic(x, int: 0, default: 1);
1138 }
1139 )",
1140 Lang_C99, "", Lang_C99);
1141
1142 auto ToResults =
1143 match(genericSelectionExpr().bind("expr"), To->getASTContext());
1144 auto FromResults =
1145 match(genericSelectionExpr().bind("expr"), From->getASTContext());
1146
1147 const GenericSelectionExpr *FromGenericSelectionExpr =
1148 selectFirst<GenericSelectionExpr>("expr", FromResults);
1149 ASSERT_TRUE(FromGenericSelectionExpr);
1150
1151 const GenericSelectionExpr *ToGenericSelectionExpr =
1152 selectFirst<GenericSelectionExpr>("expr", ToResults);
1153 ASSERT_TRUE(ToGenericSelectionExpr);
1154
1155 EXPECT_EQ(FromGenericSelectionExpr->isResultDependent(),
1156 ToGenericSelectionExpr->isResultDependent());
1157 EXPECT_EQ(FromGenericSelectionExpr->getResultIndex(),
1158 ToGenericSelectionExpr->getResultIndex());
1159}
1160
1161TEST_P(ASTImporterOptionSpecificTestBase,
1162 ImportFunctionWithBackReferringParameter) {
1163 Decl *From, *To;
1164 std::tie(From, To) = getImportedDecl(
1165 R"(
1166 template <typename T> struct X {};
1167
1168 void declToImport(int y, X<int> &x) {}
1169
1170 template <> struct X<int> {
1171 void g() {
1172 X<int> x;
1173 declToImport(0, x);
1174 }
1175 };
1176 )",
1177 Lang_CXX03, "", Lang_CXX03);
1178
1179 MatchVerifier<Decl> Verifier;
1180 auto Matcher = functionDecl(hasName("declToImport"),
1181 parameterCountIs(2),
1182 hasParameter(0, hasName("y")),
1183 hasParameter(1, hasName("x")),
1184 hasParameter(1, hasType(asString("X<int> &"))));
1185 ASSERT_TRUE(Verifier.match(From, Matcher));
1186 EXPECT_TRUE(Verifier.match(To, Matcher));
1187}
1188
1189TEST_P(ASTImporterOptionSpecificTestBase,
1190 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1191 Decl *From, *To;
1192 std::tie(From, To) =
1193 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1194 "void instantiate() { declToImport<int>(); }",
1195 Lang_CXX03, "", Lang_CXX03);
1196
1197 auto Check = [](Decl *D) -> bool {
1198 auto TU = D->getTranslationUnitDecl();
1199 for (auto Child : TU->decls()) {
1200 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1201 if (FD->getNameAsString() == "declToImport") {
1202 GTEST_NONFATAL_FAILURE_(
1203 "TU should not contain any FunctionDecl with name declToImport");
1204 return false;
1205 }
1206 }
1207 }
1208 return true;
1209 };
1210
1211 ASSERT_TRUE(Check(From));
1212 EXPECT_TRUE(Check(To));
1213}
1214
1215TEST_P(ASTImporterOptionSpecificTestBase,
1216 TUshouldNotContainTemplatedDeclOfClassTemplates) {
1217 Decl *From, *To;
1218 std::tie(From, To) =
1219 getImportedDecl("template <typename T> struct declToImport { T t; };"
1220 "void instantiate() { declToImport<int>(); }",
1221 Lang_CXX03, "", Lang_CXX03);
1222
1223 auto Check = [](Decl *D) -> bool {
1224 auto TU = D->getTranslationUnitDecl();
1225 for (auto Child : TU->decls()) {
1226 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1227 if (RD->getNameAsString() == "declToImport") {
1228 GTEST_NONFATAL_FAILURE_(
1229 "TU should not contain any CXXRecordDecl with name declToImport");
1230 return false;
1231 }
1232 }
1233 }
1234 return true;
1235 };
1236
1237 ASSERT_TRUE(Check(From));
1238 EXPECT_TRUE(Check(To));
1239}
1240
1241TEST_P(ASTImporterOptionSpecificTestBase,
1242 TUshouldNotContainTemplatedDeclOfTypeAlias) {
1243 Decl *From, *To;
1244 std::tie(From, To) =
1245 getImportedDecl(
1246 "template <typename T> struct X {};"
1247 "template <typename T> using declToImport = X<T>;"
1248 "void instantiate() { declToImport<int> a; }",
1249 Lang_CXX11, "", Lang_CXX11);
1250
1251 auto Check = [](Decl *D) -> bool {
1252 auto TU = D->getTranslationUnitDecl();
1253 for (auto Child : TU->decls()) {
1254 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1255 if (AD->getNameAsString() == "declToImport") {
1256 GTEST_NONFATAL_FAILURE_(
1257 "TU should not contain any TypeAliasDecl with name declToImport");
1258 return false;
1259 }
1260 }
1261 }
1262 return true;
1263 };
1264
1265 ASSERT_TRUE(Check(From));
1266 EXPECT_TRUE(Check(To));
1267}
1268
1269TEST_P(ASTImporterOptionSpecificTestBase,
1270 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
1271
1272 Decl *From, *To;
1273 std::tie(From, To) = getImportedDecl(
1274 R"(
1275 template<class T>
1276 class Base {};
1277 class declToImport : public Base<declToImport> {};
1278 )",
1279 Lang_CXX03, "", Lang_CXX03);
1280
1281 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1282 auto Pattern =
1283 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1284 ASSERT_TRUE(
1285 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1286 EXPECT_TRUE(
1287 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1288
1289 // Check that the ClassTemplateSpecializationDecl is the child of the
1290 // ClassTemplateDecl.
1291 Pattern = translationUnitDecl(has(classTemplateDecl(
1292 hasName("Base"), has(classTemplateSpecializationDecl()))));
1293 ASSERT_TRUE(
1294 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1295 EXPECT_TRUE(
1296 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1297}
1298
1299AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1300 size_t Index = 0;
1301 for (Decl *D : Node.decls()) {
1302 if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {
1303 auto *ND = cast<NamedDecl>(D);
1304 if (Index == Order.size())
1305 return false;
1306 if (ND->getName() != Order[Index])
1307 return false;
1308 ++Index;
1309 }
1310 }
1311 return Index == Order.size();
1312}
1313
1314TEST_P(ASTImporterOptionSpecificTestBase,
1315 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1316 Decl *From, *To;
1317 std::tie(From, To) = getImportedDecl(
1318 R"(
1319 namespace NS {
1320 template<class T>
1321 class X {};
1322 template class X<int>;
1323 }
1324 )",
1325 Lang_CXX03, "", Lang_CXX03, "NS");
1326
1327 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1328 // ClassTemplateDecl.
1329 auto Pattern = namespaceDecl(has(classTemplateDecl(
1330 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1331 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1332 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1333
1334 // Check that the ClassTemplateSpecializationDecl is the child of the
1335 // NamespaceDecl.
1336 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1337 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1338 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1339}
1340
1341TEST_P(ASTImporterOptionSpecificTestBase,
1342 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1343 Decl *From, *To;
1344 std::tie(From, To) =
1345 getImportedDecl(
1346 "struct declToImport { int a; int b; };",
1347 Lang_CXX11, "", Lang_CXX11);
1348
1349 MatchVerifier<Decl> Verifier;
1350 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1351 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1352}
1353
1354TEST_P(ASTImporterOptionSpecificTestBase,
1355 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1356 Decl *From, *To;
1357 std::tie(From, To) = getImportedDecl(
1358 // The original recursive algorithm of ASTImporter first imports 'c' then
1359 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1360 R"s(
1361 struct declToImport {
1362 int a = c + b;
1363 int b = 1;
1364 int c = 2;
1365 };
1366 )s",
1367 Lang_CXX11, "", Lang_CXX11);
1368
1369 MatchVerifier<Decl> Verifier;
1370 ASSERT_TRUE(
1371 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1372 EXPECT_TRUE(
1373 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1374}
1375
1376TEST_P(ASTImporterOptionSpecificTestBase,
1377 CXXRecordDeclFieldAndIndirectFieldOrder) {
1378 Decl *From, *To;
1379 std::tie(From, To) = getImportedDecl(
1380 // First field is "a", then the field for unnamed union, then "b" and "c"
1381 // from it (indirect fields), then "d".
1382 R"s(
1383 struct declToImport {
1384 int a = d;
1385 union {
1386 int b;
1387 int c;
1388 };
1389 int d;
1390 };
1391 )s",
1392 Lang_CXX11, "", Lang_CXX11);
1393
1394 MatchVerifier<Decl> Verifier;
1395 ASSERT_TRUE(Verifier.match(
1396 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1397 EXPECT_TRUE(Verifier.match(
1398 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1399}
1400
1401TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
1402 Decl *From, *To;
1403 std::tie(From, To) = getImportedDecl(
1404 R"(
1405 struct declToImport {
1406 };
1407 )",
1408 Lang_CXX03, "", Lang_CXX03);
1409
1410 MatchVerifier<Decl> Verifier;
1411 // Match the implicit Decl.
1412 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1413 ASSERT_TRUE(Verifier.match(From, Matcher));
1414 EXPECT_TRUE(Verifier.match(To, Matcher));
1415}
1416
1417TEST_P(ASTImporterOptionSpecificTestBase,
1418 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1419 Decl *From, *To;
1420 std::tie(From, To) = getImportedDecl(
1421 R"(
1422 template <typename U>
1423 struct declToImport {
1424 };
1425 )",
1426 Lang_CXX03, "", Lang_CXX03);
1427
1428 MatchVerifier<Decl> Verifier;
1429 // Match the implicit Decl.
1430 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1431 ASSERT_TRUE(Verifier.match(From, Matcher));
1432 EXPECT_TRUE(Verifier.match(To, Matcher));
1433}
1434
1435TEST_P(ASTImporterOptionSpecificTestBase,
1436 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
1437 Decl *From, *To;
1438 std::tie(From, To) = getImportedDecl(
1439 R"(
1440 template<class T>
1441 class Base {};
1442 class declToImport : public Base<declToImport> {};
1443 )",
1444 Lang_CXX03, "", Lang_CXX03);
1445
1446 auto hasImplicitClass = has(cxxRecordDecl());
1447 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1448 hasName("Base"),
1449 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1450 ASSERT_TRUE(
1451 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1452 EXPECT_TRUE(
1453 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1454}
1455
1456TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
1457 Decl *From, *To;
1458 std::tie(From, To) =
1459 getImportedDecl("void declToImport() {}", Lang_CXX03, "", Lang_CXX03);
1460
1461 MatchVerifier<Decl> Verifier;
1462 auto Matcher = functionDecl();
1463 ASSERT_TRUE(Verifier.match(From, Matcher));
1464 EXPECT_TRUE(Verifier.match(To, Matcher));
1465 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1466}
1467
1468TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
1469 Decl *FromTU = getTuDecl(
1470 R"(
1471 struct X {};
1472 void operator<<(int, X);
1473 )",
1474 Lang_CXX03);
1475 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1476 const Decl *To = Import(From, Lang_CXX03);
1477 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1478}
1479
1480TEST_P(ASTImporterOptionSpecificTestBase,
1481 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1482 Decl *From, *To;
1483 std::tie(From, To) = getImportedDecl(
1484 R"(
1485 template<class T>
1486 class Base { int a; };
1487 class declToImport : Base<declToImport> {};
1488 )",
1489 Lang_CXX03, "", Lang_CXX03);
1490
1491 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1492 hasName("Base"),
1493 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1494 ASSERT_TRUE(
1495 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1496 EXPECT_TRUE(
1497 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1498}
1499
1500TEST_P(ASTImporterOptionSpecificTestBase,
1501 ImportDefinitionOfClassTemplateAfterFwdDecl) {
1502 {
1503 Decl *FromTU = getTuDecl(
1504 R"(
1505 template <typename T>
1506 struct B;
1507 )",
1508 Lang_CXX03, "input0.cc");
1509 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1510 FromTU, classTemplateDecl(hasName("B")));
1511
1512 Import(FromD, Lang_CXX03);
1513 }
1514
1515 {
1516 Decl *FromTU = getTuDecl(
1517 R"(
1518 template <typename T>
1519 struct B {
1520 void f();
1521 };
1522 )",
1523 Lang_CXX03, "input1.cc");
1524 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1525 FromTU, functionDecl(hasName("f")));
1526 Import(FromD, Lang_CXX03);
1527 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1528 FromTU, classTemplateDecl(hasName("B")));
1529 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));
1530 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1531 }
1532}
1533
1534TEST_P(ASTImporterOptionSpecificTestBase,
1535 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1536 Decl *ToTU = getToTuDecl(
1537 R"(
1538 template <typename T>
1539 struct B {
1540 void f();
1541 };
1542
1543 template <typename T>
1544 struct B;
1545 )",
1546 Lang_CXX03);
1547 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1548 [](const ClassTemplateDecl *T) {
1549 return T->isThisDeclarationADefinition();
1550 })
1551 .match(ToTU, classTemplateDecl()));
1552
1553 Decl *FromTU = getTuDecl(
1554 R"(
1555 template <typename T>
1556 struct B {
1557 void f();
1558 };
1559 )",
1560 Lang_CXX03, "input1.cc");
1561 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1562 FromTU, classTemplateDecl(hasName("B")));
1563
1564 Import(FromD, Lang_CXX03);
1565
1566 // We should have only one definition.
1567 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1568 [](const ClassTemplateDecl *T) {
1569 return T->isThisDeclarationADefinition();
1570 })
1571 .match(ToTU, classTemplateDecl()));
1572}
1573
1574TEST_P(ASTImporterOptionSpecificTestBase,
1575 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1576 Decl *ToTU = getToTuDecl(
1577 R"(
1578 struct B {
1579 void f();
1580 };
1581
1582 struct B;
1583 )",
1584 Lang_CXX03);
1585 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1586 ToTU, cxxRecordDecl(unless(isImplicit()))));
1587
1588 Decl *FromTU = getTuDecl(
1589 R"(
1590 struct B {
1591 void f();
1592 };
1593 )",
1594 Lang_CXX03, "input1.cc");
1595 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1596 FromTU, cxxRecordDecl(hasName("B")));
1597
1598 Import(FromD, Lang_CXX03);
1599
1600 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1601 ToTU, cxxRecordDecl(unless(isImplicit()))));
1602}
1603
1604static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1605 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1606 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1607 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1608 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1609}
1610static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1611 SourceManager &SM1, SourceManager &SM2) {
1612 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1613 FullSourceLoc{ Range2.getBegin(), SM2 });
1614 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1615 FullSourceLoc{ Range2.getEnd(), SM2 });
1616}
1617TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
1618 Decl *FromTU = getTuDecl(
1619 R"(
1620 #define MFOO(arg) arg = arg + 1
1621
1622 void foo() {
1623 int a = 5;
1624 MFOO(a);
1625 }
1626 )",
1627 Lang_CXX03);
1628 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1629 auto ToD = Import(FromD, Lang_CXX03);
1630
1631 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1632 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1633 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1634 auto FromRHS =
1635 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1636
1637 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1638 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1639 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1640 FromSM);
1641 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1642 FromSM);
1643 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1644 FromSM);
1645}
1646
1647TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
1648 Decl *FromTU = getTuDecl(
1649 R"(
1650 #define FUNC_INT void declToImport
1651 #define FUNC FUNC_INT
1652 FUNC(int a);
1653 )",
1654 Lang_CXX03);
1655 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1656 auto ToD = Import(FromD, Lang_CXX03);
1657
1658 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1659 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1660 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1661 FromSM);
1662}
1663
1664TEST_P(
1665 ASTImporterOptionSpecificTestBase,
1666 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
1667 Decl *ToTU = getToTuDecl(
1668 R"(
1669 template <typename T>
1670 struct B;
1671
1672 template <>
1673 struct B<int> {};
1674
1675 template <>
1676 struct B<int>;
1677 )",
1678 Lang_CXX03);
1679 // We should have only one definition.
1680 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1681 [](const ClassTemplateSpecializationDecl *T) {
1682 return T->isThisDeclarationADefinition();
1683 })
1684 .match(ToTU, classTemplateSpecializationDecl()));
1685
1686 Decl *FromTU = getTuDecl(
1687 R"(
1688 template <typename T>
1689 struct B;
1690
1691 template <>
1692 struct B<int> {};
1693 )",
1694 Lang_CXX03, "input1.cc");
1695 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1696 FromTU, classTemplateSpecializationDecl(hasName("B")));
1697
1698 Import(FromD, Lang_CXX03);
1699
1700 // We should have only one definition.
1701 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1702 [](const ClassTemplateSpecializationDecl *T) {
1703 return T->isThisDeclarationADefinition();
1704 })
1705 .match(ToTU, classTemplateSpecializationDecl()));
1706}
1707
1708TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
1709 Decl *FromTU = getTuDecl(
1710 R"(
1711 struct { int a; int b; } object0 = { 2, 3 };
1712 struct { int x; int y; int z; } object1;
1713 )",
1714 Lang_CXX03, "input0.cc");
1715
1716 auto *Obj0 =
1717 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1718 auto *From0 = getRecordDecl(Obj0);
1719 auto *Obj1 =
1720 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1721 auto *From1 = getRecordDecl(Obj1);
1722
1723 auto *To0 = Import(From0, Lang_CXX03);
1724 auto *To1 = Import(From1, Lang_CXX03);
1725
1726 EXPECT_TRUE(To0);
1727 EXPECT_TRUE(To1);
1728 EXPECT_NE(To0, To1);
1729 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1730}
1731
1732TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
1733 auto *Code =
1734 R"(
1735 struct X {
1736 struct { int a; };
1737 struct { int b; };
1738 };
1739 )";
1740 Decl *FromTU0 = getTuDecl(Code, Lang_C99, "input0.c");
1741
1742 Decl *FromTU1 = getTuDecl(Code, Lang_C99, "input1.c");
1743
1744 auto *X0 =
1745 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1746 auto *X1 =
1747 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1748 Import(X0, Lang_C99);
1749 Import(X1, Lang_C99);
1750
1751 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1752 // We expect no (ODR) warning during the import.
1753 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1754 EXPECT_EQ(1u,
1755 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1756}
1757
1758TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
1759 Decl *FromTU0 = getTuDecl(
1760 R"(
1761 struct X {
1762 struct { int a; };
1763 struct { int b; };
1764 };
1765 )",
1766 Lang_C99, "input0.c");
1767
1768 Decl *FromTU1 = getTuDecl(
1769 R"(
1770 struct X { // reversed order
1771 struct { int b; };
1772 struct { int a; };
1773 };
1774 )",
1775 Lang_C99, "input1.c");
1776
1777 auto *X0 =
1778 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1779 auto *X1 =
1780 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1781 Import(X0, Lang_C99);
1782 Import(X1, Lang_C99);
1783
1784 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1785 // We expect one (ODR) warning during the import.
1786 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1787 EXPECT_EQ(1u,
1788 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1789}
1790
1791TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
1792 auto Pattern = varDecl(hasName("x"));
1793 VarDecl *Imported1;
1794 {
1795 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX03, "input0.cc");
1796 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1797 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));
1798 }
1799 VarDecl *Imported2;
1800 {
1801 Decl *FromTU = getTuDecl("int x;", Lang_CXX03, "input1.cc");
1802 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1803 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));
1804 }
1805 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1806 EXPECT_FALSE(Imported2->isUsed(false));
1807 {
1808 Decl *FromTU = getTuDecl("extern int x; int f() { return x; }", Lang_CXX03,
1809 "input2.cc");
1810 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1811 FromTU, functionDecl(hasName("f")));
1812 Import(FromD, Lang_CXX03);
1813 }
1814 EXPECT_TRUE(Imported2->isUsed(false));
1815}
1816
1817TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
1818 auto Pattern = varDecl(hasName("x"));
1819 VarDecl *ExistingD;
1820 {
1821 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX03);
1822 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1823 }
1824 EXPECT_FALSE(ExistingD->isUsed(false));
1825 {
1826 Decl *FromTU =
1827 getTuDecl("int x = 1; int f() { return x; }", Lang_CXX03, "input1.cc");
1828 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1829 FromTU, functionDecl(hasName("f")));
1830 Import(FromD, Lang_CXX03);
1831 }
1832 EXPECT_TRUE(ExistingD->isUsed(false));
1833}
1834
1835TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
1836 auto Pattern = varDecl(hasName("a"));
1837 VarDecl *ExistingD;
1838 {
1839 Decl *ToTU = getToTuDecl(
1840 R"(
1841 struct A {
1842 static const int a = 1;
1843 };
1844 )",
1845 Lang_CXX03);
1846 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1847 }
1848 EXPECT_FALSE(ExistingD->isUsed(false));
1849 {
1850 Decl *FromTU = getTuDecl(
1851 R"(
1852 struct A {
1853 static const int a = 1;
1854 };
1855 const int *f() { return &A::a; } // requires storage,
1856 // thus used flag will be set
1857 )",
1858 Lang_CXX03, "input1.cc");
1859 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1860 FromTU, functionDecl(hasName("f")));
1861 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1862 ASSERT_TRUE(FromD->isUsed(false));
1863 Import(FromFunD, Lang_CXX03);
1864 }
1865 EXPECT_TRUE(ExistingD->isUsed(false));
1866}
1867
1868TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
1869 auto Pattern = varDecl(hasName("x"));
1870
1871 Decl *FromTU = getTuDecl("int x;", Lang_CXX03, "input0.cc");
1872 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1873
1874 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));
1875
1876 ASSERT_FALSE(Imported1->isUsed(false));
1877
1878 FromD->setIsUsed();
1879 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));
1880
1881 EXPECT_EQ(Imported1, Imported2);
1882 EXPECT_TRUE(Imported2->isUsed(false));
1883}
1884
1885struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
1886
1887TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
1888 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX03);
1889 auto Pattern = functionDecl(hasName("f"));
1890 auto *From =
1891 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
1892
1893 Decl *ImportedD = Import(From, Lang_CXX03);
1894 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1895
1896 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1897 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1898 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1899 EXPECT_TRUE(ImportedD == To0);
1900 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1901 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1902 EXPECT_EQ(To1->getPreviousDecl(), To0);
1903}
1904
1905TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1906 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX03);
1907 auto Pattern = functionDecl(hasName("f"));
1908 auto *From =
1909 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
1910
1911 Decl *ImportedD = Import(From, Lang_CXX03);
1912 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1913
1914 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1915 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1916 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1917 EXPECT_TRUE(ImportedD == To1);
1918 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1919 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1920 EXPECT_EQ(To1->getPreviousDecl(), To0);
1921}
1922
1923TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1924 auto Code =
1925 R"(
1926 struct B { virtual void f(); };
1927 void B::f() {}
1928 struct D : B { void f(); };
1929 )";
1930 auto Pattern =
1931 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1932 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
1933 CXXMethodDecl *Proto =
1934 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1935
1936 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1937 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX03));
1938 EXPECT_EQ(To->size_overridden_methods(), 1u);
1939}
1940
1941TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1942 auto Code =
1943 R"(
1944 struct B { virtual void f(); };
1945 void B::f() {}
1946 )";
1947 auto Pattern =
1948 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1949 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
1950 CXXMethodDecl *Proto =
1951 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1952 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1953
1954 ASSERT_TRUE(Proto->isVirtual());
1955 ASSERT_TRUE(Def->isVirtual());
1956 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX03));
1957 EXPECT_TRUE(To->isVirtual());
1958}
1959
1960TEST_P(ImportFunctions,
1961 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
1962 Decl *ToTU = getToTuDecl(
1963 R"(
1964 void f() {}
1965 void f();
1966 )",
1967 Lang_CXX03);
1968 ASSERT_EQ(1u,
1969 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1970 return FD->doesThisDeclarationHaveABody();
1971 }).match(ToTU, functionDecl()));
1972
1973 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX03, "input0.cc");
1974 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1975
1976 Import(FromD, Lang_CXX03);
1977
1978 EXPECT_EQ(1u,
1979 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1980 return FD->doesThisDeclarationHaveABody();
1981 }).match(ToTU, functionDecl()));
1982}
1983
1984TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
1985 auto Code =
1986 R"(
1987 struct B { virtual void f(); };
1988 struct D:B { void f(); };
1989 )";
1990 auto BFP =
1991 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1992 auto DFP =
1993 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1994
1995 Decl *FromTU0 = getTuDecl(Code, Lang_CXX03);
1996 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
1997 Import(DF, Lang_CXX03);
1998
1999 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2000 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2001 Import(BF, Lang_CXX03);
2002
2003 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2004
2005 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2006 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2007}
2008
2009TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2010 auto CodeWithoutDef =
2011 R"(
2012 struct B { virtual void f(); };
2013 struct D:B { void f(); };
2014 )";
2015 auto CodeWithDef =
2016 R"(
2017 struct B { virtual void f(){}; };
2018 struct D:B { void f(){}; };
2019 )";
2020 auto BFP =
2021 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2022 auto DFP =
2023 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2024 auto BFDefP = cxxMethodDecl(
2025 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2026 auto DFDefP = cxxMethodDecl(
2027 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2028 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2029
2030 {
2031 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX03, "input0.cc");
2032 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2033 Import(FromD, Lang_CXX03);
2034 }
2035 {
2036 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX03, "input1.cc");
2037 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2038 Import(FromB, Lang_CXX03);
2039 }
2040
2041 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2042
2043 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2044 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2045 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2046 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2047 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2048}
2049
2050TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2051 auto Code =
2052 R"(
2053 struct B { virtual void f(); };
2054 struct D:B { void f(); };
2055 void B::f(){};
2056 )";
2057
2058 auto BFP =
2059 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2060 auto BFDefP = cxxMethodDecl(
2061 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2062 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2063 unless(isDefinition()));
2064
2065 Decl *FromTU0 = getTuDecl(Code, Lang_CXX03);
2066 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2067 Import(D, Lang_CXX03);
2068
2069 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2070 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2071 Import(B, Lang_CXX03);
2072
2073 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2074
2075 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2076 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2077
2078 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2079 ToTU, cxxRecordDecl(hasName("B")));
2080 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2081 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2082 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2083
2084 // The definition should be out-of-class.
2085 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2086 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2087 ToBFOutOfClass->getLexicalDeclContext());
2088 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2089 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2090
2091 // Check that the redecl chain is intact.
2092 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2093}
2094
2095TEST_P(ImportFunctions,
2096 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2097 auto CodeTU0 =
2098 R"(
2099 struct B { virtual void f(); };
2100 struct D:B { void f(); };
2101 )";
2102 auto CodeTU1 =
2103 R"(
2104 struct B { virtual void f(); };
2105 struct D:B { void f(); };
2106 void B::f(){}
2107 void D::f(){}
2108 void foo(B &b, D &d) { b.f(); d.f(); }
2109 )";
2110
2111 auto BFP =
2112 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2113 auto BFDefP = cxxMethodDecl(
2114 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2115 auto DFP =
2116 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2117 auto DFDefP = cxxMethodDecl(
2118 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2119 auto FooDef = functionDecl(hasName("foo"));
2120
2121 {
2122 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX03, "input0.cc");
2123 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2124 Import(D, Lang_CXX03);
2125 }
2126
2127 {
2128 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX03, "input1.cc");
2129 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2130 Import(Foo, Lang_CXX03);
2131 }
2132
2133 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2134
2135 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2136 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2137 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2138 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2139
2140 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2141 ToTU, cxxRecordDecl(hasName("B")));
2142 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2143 ToTU, cxxRecordDecl(hasName("D")));
2144 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2145 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2146 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2147 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2148 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2149 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2150
2151 // The definition should be out-of-class.
2152 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2153 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2154 ToBFOutOfClass->getLexicalDeclContext());
2155 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2156 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2157
2158 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2159 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2160 ToDFOutOfClass->getLexicalDeclContext());
2161 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2162 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2163
2164 // Check that the redecl chain is intact.
2165 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2166 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2167}
2168
2169TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2170 std::string Code = "static int v; static int v = 0;";
2171 auto Pattern = varDecl(hasName("v"));
2172
2173 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C99, "input0.c");
2174
2175 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2176 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2177
2178 auto *To0 = Import(From0, Lang_C99);
2179 auto *To1 = Import(From1, Lang_C99);
2180
2181 EXPECT_TRUE(To0);
2182 ASSERT_TRUE(To1);
2183 EXPECT_NE(To0, To1);
2184 EXPECT_EQ(To1->getPreviousDecl(), To0);
2185}
2186
2187TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2188 TranslationUnitDecl *FromTu =
2189 getTuDecl("namespace NS0 { namespace { void f(); } }"
2190 "namespace NS1 { namespace { void f(); } }",
2191 Lang_CXX03, "input0.cc");
2192 auto Pattern = functionDecl(hasName("f"));
2193
2194 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2195 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2196
2197 auto *ToF0 = Import(FromF0, Lang_CXX03);
2198 auto *ToF1 = Import(FromF1, Lang_CXX03);
2199
2200 EXPECT_TRUE(ToF0);
2201 ASSERT_TRUE(ToF1);
2202 EXPECT_NE(ToF0, ToF1);
2203 EXPECT_FALSE(ToF1->getPreviousDecl());
2204}
2205
2206TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2207 {
2208 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2209 Lang_CXX03, "input0.cc");
2210 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2211 FromTU, functionDecl(hasName("g0")));
2212
2213 Import(FromD, Lang_CXX03);
2214 }
2215 {
2216 Decl *FromTU =
2217 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2218 Lang_CXX03, "input1.cc");
2219 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2220 FromTU, functionDecl(hasName("g1")));
2221 Import(FromD, Lang_CXX03);
2222 }
2223
2224 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2225 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2226 2u);
2227}
2228
2229TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2230 Decl *FromTU = getTuDecl(
2231 R"(
2232 void foo() {
2233 (void)[]() { ; };
2234 }
2235 )",
2236 Lang_CXX11);
2237 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2238 FromTU, functionDecl(hasName("foo")));
2239 auto *ToD = Import(FromD, Lang_CXX03);
2240 EXPECT_TRUE(ToD);
2241 CXXRecordDecl *LambdaRec =
2242 cast<LambdaExpr>(cast<CStyleCastExpr>(
2243 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2244 ->getSubExpr())
2245 ->getLambdaClass();
2246 EXPECT_TRUE(LambdaRec->getDestructor());
2247}
2248
2249TEST_P(ImportFunctions,
2250 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2251 Decl *FromTU = getTuDecl(
2252 R"(
2253 struct X {
2254 template <typename T>
2255 void foo(){}
2256 };
2257 void f() {
2258 X x;
2259 x.foo<int>();
2260 }
2261 )",
2262 Lang_CXX03);
2263 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2264 FromTU, functionDecl(hasName("f")));
2265 auto *ToD = Import(FromD, Lang_CXX03);
2266 EXPECT_TRUE(ToD);
2267 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2268 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2269}
2270
2271TEST_P(ImportFunctions,
2272 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2273 Decl *FromTU = getTuDecl(
2274 R"(
2275 struct X {
2276 template <typename T>
2277 void foo(){}
2278 };
2279 template <typename T>
2280 void f() {
2281 X x;
2282 x.foo<T>();
2283 }
2284 void g() {
2285 f<int>();
2286 }
2287 )",
2288 Lang_CXX03);
2289 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2290 FromTU, functionDecl(hasName("g")));
2291 auto *ToD = Import(FromD, Lang_CXX03);
2292 EXPECT_TRUE(ToD);
2293 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2294 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2295 ToTU, translationUnitDecl(hasDescendant(
2296 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2297}
2298
2299struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};
2300
2301TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {
2302 auto Code =
2303 R"(
2304 class X {
2305 template <class T>
2306 void f(T t);
2307 };
2308 )";
2309 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2310 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2311 FromTU1, functionTemplateDecl(hasName("f")));
2312 auto *ToD1 = Import(FromD1, Lang_CXX03);
2313 Decl *FromTU2 = getTuDecl(Code, Lang_CXX03, "input2.cc");
2314 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2315 FromTU2, functionTemplateDecl(hasName("f")));
2316 auto *ToD2 = Import(FromD2, Lang_CXX03);
2317 EXPECT_EQ(ToD1, ToD2);
2318}
2319
2320TEST_P(ImportFunctionTemplates,
2321 ImportFunctionTemplateWithDefInRecordDeclTwice) {
2322 auto Code =
2323 R"(
2324 class X {
2325 template <class T>
2326 void f(T t);
2327 };
2328 template <class T>
2329 void X::f(T t) {};
2330 )";
2331 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2332 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2333 FromTU1, functionTemplateDecl(hasName("f")));
2334 auto *ToD1 = Import(FromD1, Lang_CXX03);
2335 Decl *FromTU2 = getTuDecl(Code, Lang_CXX03, "input2.cc");
2336 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2337 FromTU2, functionTemplateDecl(hasName("f")));
2338 auto *ToD2 = Import(FromD2, Lang_CXX03);
2339 EXPECT_EQ(ToD1, ToD2);
2340}
2341
2342TEST_P(ImportFunctionTemplates,
2343 ImportFunctionWhenThereIsAFunTemplateWithSameName) {
2344 getToTuDecl(
2345 R"(
2346 template <typename T>
2347 void foo(T) {}
2348 void foo();
2349 )",
2350 Lang_CXX03);
2351 Decl *FromTU = getTuDecl("void foo();", Lang_CXX03);
2352 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2353 FromTU, functionDecl(hasName("foo")));
2354 auto *ImportedD = Import(FromD, Lang_CXX03);
2355 EXPECT_TRUE(ImportedD);
2356}
2357
2358TEST_P(ImportFunctionTemplates,
2359 ImportConstructorWhenThereIsAFunTemplateWithSameName) {
2360 auto Code =
2361 R"(
2362 struct Foo {
2363 template <typename T>
2364 Foo(T) {}
2365 Foo();
2366 };
2367 )";
2368 getToTuDecl(Code, Lang_CXX03);
2369 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
2370 auto *FromD =
2371 LastDeclMatcher<CXXConstructorDecl>().match(FromTU, cxxConstructorDecl());
2372 auto *ImportedD = Import(FromD, Lang_CXX03);
2373 EXPECT_TRUE(ImportedD);
2374}
2375
2376TEST_P(ImportFunctionTemplates,
2377 ImportOperatorWhenThereIsAFunTemplateWithSameName) {
2378 getToTuDecl(
2379 R"(
2380 template <typename T>
2381 void operator<(T,T) {}
2382 struct X{};
2383 void operator<(X, X);
2384 )",
2385 Lang_CXX03);
2386 Decl *FromTU = getTuDecl(
2387 R"(
2388 struct X{};
2389 void operator<(X, X);
2390 )",
2391 Lang_CXX03);
2392 auto *FromD = LastDeclMatcher<FunctionDecl>().match(
2393 FromTU, functionDecl(hasOverloadedOperatorName("<")));
2394 auto *ImportedD = Import(FromD, Lang_CXX03);
2395 EXPECT_TRUE(ImportedD);
2396}
2397
2398struct ImportFriendFunctions : ImportFunctions {};
2399
2400TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2401 auto Pattern = functionDecl(hasName("f"));
2402
2403 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2404 "void f();",
2405 Lang_CXX03, "input0.cc");
2406 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2407
2408 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2409 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2410 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2411 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2412 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2413 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2414 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2415}
2416
2417TEST_P(ImportFriendFunctions,
2418 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2419 auto Pattern = functionDecl(hasName("f"));
2420
2421 Decl *FromTU = getTuDecl("void f();"
2422 "struct X { friend void f(); };",
2423 Lang_CXX03, "input0.cc");
2424 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2425
2426 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2427 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2428 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2429 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2430 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2431 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2432 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2433}
2434
2435TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2436 auto Pattern = functionDecl(hasName("f"));
2437
2438 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2439 "void f();",
2440 Lang_CXX03, "input0.cc");
2441 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2442
2443 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2444 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2445 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2446 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2447 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2448 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2449 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2450}
2451
2452TEST_P(ImportFriendFunctions,
2453 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2454 auto Pattern = functionDecl(hasName("f"));
2455
2456 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2457 "void f(){}",
2458 Lang_CXX03, "input0.cc");
2459 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2460
2461 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2462 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2463 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2464 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2465 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2466 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2467 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2468}
2469
2470TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
2471 auto Pattern = functionDecl(hasName("f"));
2472
2473 Decl *FromTU = getTuDecl(
2474 R"(
2475 class X;
2476 void f(X *x){}
2477 class X{
2478 friend void f(X *x);
2479 };
2480 )",
2481 Lang_CXX03, "input0.cc");
2482 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2483
2484 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2485 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2486 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2487 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2488 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2489 .match(ToTU, friendDecl())
2490 ->getFriendDecl());
2491 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2492 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2493 // The parameters must refer the same type
2494 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2495 (*ImportedD->param_begin())->getOriginalType());
2496}
2497
2498TEST_P(ImportFriendFunctions,
2499 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
2500 auto Pattern = functionDecl(hasName("f"));
2501
2502 Decl *FromTU = getTuDecl(
2503 R"(
2504 class X;
2505 void f(X *x){}
2506 class X{
2507 friend void f(X *x);
2508 };
2509 )",
2510 Lang_CXX03, "input0.cc");
2511 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2512
2513 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2514 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2515 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2516 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2517 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2518 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2519
2520 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2521 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2522 // The parameters must refer the same type
2523 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2524 (*ImportedD->param_begin())->getOriginalType());
2525}
2526
2527TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2528 auto Pattern = functionDecl(hasName("f"));
2529
2530 FunctionDecl *ImportedD;
2531 {
2532 Decl *FromTU =
2533 getTuDecl("struct X { friend void f(){} };", Lang_CXX03, "input0.cc");
2534 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2535 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2536 }
2537 FunctionDecl *ImportedD1;
2538 {
2539 Decl *FromTU = getTuDecl("void f();", Lang_CXX03, "input1.cc");
2540 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2541 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2542 }
2543
2544 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2545 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2546 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2547 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2548 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2549}
2550
2551TEST_P(ImportFriendFunctions, Lookup) {
2552 auto FunctionPattern = functionDecl(hasName("f"));
2553 auto ClassPattern = cxxRecordDecl(hasName("X"));
2554
2555 TranslationUnitDecl *FromTU =
2556 getTuDecl("struct X { friend void f(); };", Lang_CXX03, "input0.cc");
2557 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2558 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2559 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2560 {
2561 auto FromName = FromD->getDeclName();
2562 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2563 auto LookupRes = Class->noload_lookup(FromName);
2564 ASSERT_EQ(LookupRes.size(), 0u);
2565 LookupRes = FromTU->noload_lookup(FromName);
2566 ASSERT_EQ(LookupRes.size(), 1u);
2567 }
2568
2569 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2570 auto ToName = ToD->getDeclName();
2571
2572 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2573 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2574 auto LookupRes = Class->noload_lookup(ToName);
2575 EXPECT_EQ(LookupRes.size(), 0u);
2576 LookupRes = ToTU->noload_lookup(ToName);
2577 EXPECT_EQ(LookupRes.size(), 1u);
2578
2579 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2580 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2581 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2582 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2583}
2584
2585TEST_P(ImportFriendFunctions, LookupWithProtoAfter) {
2586 auto FunctionPattern = functionDecl(hasName("f"));
2587 auto ClassPattern = cxxRecordDecl(hasName("X"));
2588
2589 TranslationUnitDecl *FromTU =
2590 getTuDecl("struct X { friend void f(); };"
2591 // This proto decl makes f available to normal
2592 // lookup, otherwise it is hidden.
2593 // Normal C++ lookup (implemented in
2594 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2595 // returns the found `NamedDecl` only if the set IDNS is matched
2596 "void f();",
2597 Lang_CXX03, "input0.cc");
2598 auto *FromFriend =
2599 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2600 auto *FromNormal =
2601 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2602 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2603 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2604 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2605 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2606
2607 auto FromName = FromFriend->getDeclName();
2608 auto *FromClass =
2609 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2610 auto LookupRes = FromClass->noload_lookup(FromName);
2611 ASSERT_EQ(LookupRes.size(), 0u);
2612 LookupRes = FromTU->noload_lookup(FromName);
2613 ASSERT_EQ(LookupRes.size(), 1u);
2614
2615 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX03));
2616 auto ToName = ToFriend->getDeclName();
2617
2618 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2619 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2620 LookupRes = ToClass->noload_lookup(ToName);
2621 EXPECT_EQ(LookupRes.size(), 0u);
2622 LookupRes = ToTU->noload_lookup(ToName);
2623 // Test is disabled because this result is 2.
2624 EXPECT_EQ(LookupRes.size(), 1u);
2625
2626 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2627 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2628 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2629 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2630 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2631 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2632 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2633}
2634
2635TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2636 auto FunctionPattern = functionDecl(hasName("f"));
2637 auto ClassPattern = cxxRecordDecl(hasName("X"));
2638
2639 TranslationUnitDecl *FromTU = getTuDecl("void f();"
2640 "struct X { friend void f(); };",
2641 Lang_CXX03, "input0.cc");
2642 auto *FromNormal =
2643 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2644 auto *FromFriend =
2645 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2646 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2647 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2648 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2649 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2650
2651 auto FromName = FromNormal->getDeclName();
2652 auto *FromClass =
2653 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2654 auto LookupRes = FromClass->noload_lookup(FromName);
2655 ASSERT_EQ(LookupRes.size(), 0u);
2656 LookupRes = FromTU->noload_lookup(FromName);
2657 ASSERT_EQ(LookupRes.size(), 1u);
2658
2659 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX03));
2660 auto ToName = ToNormal->getDeclName();
2661 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2662
2663 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2664 LookupRes = ToClass->noload_lookup(ToName);
2665 EXPECT_EQ(LookupRes.size(), 0u);
2666 LookupRes = ToTU->noload_lookup(ToName);
2667 EXPECT_EQ(LookupRes.size(), 1u);
2668
2669 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2670 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2671 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2672 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2673 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2674 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2675 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2676}
2677
2678TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2679 auto Pattern = functionDecl(hasName("f"));
2680
2681 TranslationUnitDecl *FromNormalTU =
2682 getTuDecl("void f();", Lang_CXX03, "input0.cc");
2683 auto *FromNormalF =
2684 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2685 TranslationUnitDecl *FromFriendTU =
2686 getTuDecl("class X { friend void f(); };", Lang_CXX03, "input1.cc");
2687 auto *FromFriendF =
2688 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2689 auto FromNormalName = FromNormalF->getDeclName();
2690 auto FromFriendName = FromFriendF->getDeclName();
2691
2692 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2693 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2694 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2695 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2696 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2697 ASSERT_EQ(LookupRes.size(), 1u);
2698 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2699 ASSERT_EQ(LookupRes.size(), 1u);
2700
2701 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX03));
2702 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2703 auto ToName = ToNormalF->getDeclName();
2704 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2705 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2706 LookupRes = ToTU->noload_lookup(ToName);
2707 EXPECT_EQ(LookupRes.size(), 1u);
2708 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2709
2710 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX03));
2711 LookupRes = ToTU->noload_lookup(ToName);
2712 EXPECT_EQ(LookupRes.size(), 1u);
2713 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2714
2715 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2716 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2717
2718 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2719 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2720}
2721
2722TEST_P(ImportFriendFunctions, ImportFriendList) {
2723 TranslationUnitDecl *FromTU = getTuDecl("struct X { friend void f(); };"
2724 "void f();",
2725 Lang_CXX03, "input0.cc");
2726 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2727 FromTU, functionDecl(hasName("f")));
2728
2729 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2730 FromTU, cxxRecordDecl(hasName("X")));
2731 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2732 auto FromFriends = FromClass->friends();
2733 unsigned int FrN = 0;
2734 for (auto Fr : FromFriends) {
2735 ASSERT_EQ(Fr, FromFriend);
2736 ++FrN;
2737 }
2738 ASSERT_EQ(FrN, 1u);
2739
2740 Import(FromFriendF, Lang_CXX03);
2741 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2742 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2743 ToTU, cxxRecordDecl(hasName("X")));
2744 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2745 auto ToFriends = ToClass->friends();
2746 FrN = 0;
2747 for (auto Fr : ToFriends) {
2748 EXPECT_EQ(Fr, ToFriend);
2749 ++FrN;
2750 }
2751 EXPECT_EQ(FrN, 1u);
2752}
2753
2754AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2755 InnerMatcher) {
2756 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2757 return InnerMatcher.matches(*Typedef, Finder, Builder);
2758 return false;
2759}
2760
2761TEST_P(ImportDecl, ImportEnumSequential) {
2762 CodeFiles Samples{{"main.c",
2763 {"void foo();"
2764 "void moo();"
2765 "int main() { foo(); moo(); }",
2766 Lang_C99}},
2767
2768 {"foo.c",
2769 {"typedef enum { THING_VALUE } thing_t;"
2770 "void conflict(thing_t type);"
2771 "void foo() { (void)THING_VALUE; }"
2772 "void conflict(thing_t type) {}",
2773 Lang_C99}},
2774
2775 {"moo.c",
2776 {"typedef enum { THING_VALUE } thing_t;"
2777 "void conflict(thing_t type);"
2778 "void moo() { conflict(THING_VALUE); }",
2779 Lang_C99}}};
2780
2781 auto VerificationMatcher =
2782 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2783 hasTypedefForAnonDecl(hasName("thing_t")));
2784
2785 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2786 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2787
2788 testImportSequence(
2789 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2790 // Just check that there is only one enum decl in the result AST.
2791 "main.c", enumDecl(), VerificationMatcher);
2792
2793 // For different import order, result should be the same.
2794 testImportSequence(
2795 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2796 // Check that there is only one enum decl in the result AST.
2797 "main.c", enumDecl(), VerificationMatcher);
2798}
2799
2800TEST_P(ImportDecl, ImportFieldOrder) {
2801 MatchVerifier<Decl> Verifier;
2802 testImport("struct declToImport {"
2803 " int b = a + 2;"
2804 " int a = 5;"
2805 "};",
2806 Lang_CXX11, "", Lang_CXX11, Verifier,
2807 recordDecl(hasFieldOrder({"b", "a"})));
2808}
2809
2810const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2811 dependentScopeDeclRefExpr;
2812
2813TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
2814 MatchVerifier<Decl> Verifier;
2815 testImport("template <typename T> struct S { static T foo; };"
2816 "template <typename T> void declToImport() {"
2817 " (void) S<T>::foo;"
2818 "}"
2819 "void instantiate() { declToImport<int>(); }"
2820 "template <typename T> T S<T>::foo;",
2821 Lang_CXX11, "", Lang_CXX11, Verifier,
2822 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2823 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2824
2825 testImport("template <typename T> struct S {"
2826 "template<typename S> static void foo(){};"
2827 "};"
2828 "template <typename T> void declToImport() {"
2829 " S<T>::template foo<T>();"
2830 "}"
2831 "void instantiate() { declToImport<int>(); }",
2832 Lang_CXX11, "", Lang_CXX11, Verifier,
2833 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2834 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2835}
2836
2837const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2838 dependentNameType;
2839
2840TEST_P(ImportExpr, DependentNameType) {
2841 MatchVerifier<Decl> Verifier;
2842 testImport("template <typename T> struct declToImport {"
2843 " typedef typename T::type dependent_name;"
2844 "};",
2845 Lang_CXX11, "", Lang_CXX11, Verifier,
2846 classTemplateDecl(has(
2847 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2848}
2849
2850TEST_P(ImportExpr, UnresolvedMemberExpr) {
2851 MatchVerifier<Decl> Verifier;
2852 testImport("struct S { template <typename T> void mem(); };"
2853 "template <typename U> void declToImport() {"
2854 " S s;"
2855 " s.mem<U>();"
2856 "}"
2857 "void instantiate() { declToImport<int>(); }",
2858 Lang_CXX11, "", Lang_CXX11, Verifier,
2859 functionTemplateDecl(has(functionDecl(has(
2860 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2861}
2862
2863class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
2864public:
2865 static constexpr auto DefaultCode = R"(
2866 struct A { int x; };
2867 void f() {
2868 A a;
2869 A a1(a);
2870 A a2(A{});
2871 a = a1;
2872 a = A{};
2873 a.~A();
2874 })";
2875
2876 template <typename MatcherType>
2877 void testImportOf(
2878 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2879 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2880 }
2881
2882 template <typename MatcherType>
2883 void testNoImportOf(
2884 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2885 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2886 }
2887
2888private:
2889 template <typename MatcherType>
2890 void test(const MatcherType &MethodMatcher,
2891 const char *Code, unsigned int ExpectedCount) {
2892 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2893
2894 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2895 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2896 ToTU, ClassMatcher);
2897
2898 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
2899
2900 {
2901 CXXMethodDecl *Method =
2902 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2903 ToClass->removeDecl(Method);
2904 SharedStatePtr->getLookupTable()->remove(Method);
2905 }
2906
2907 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
2908
2909 Decl *ImportedClass = nullptr;
2910 {
2911 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2912 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2913 FromTU, ClassMatcher);
2914 ImportedClass = Import(FromClass, Lang_CXX11);
2915 }
2916
2917 EXPECT_EQ(ToClass, ImportedClass);
2918 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2919 ExpectedCount);
2920 }
2921};
2922
2923TEST_P(ImportImplicitMethods, DefaultConstructor) {
2924 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2925}
2926
2927TEST_P(ImportImplicitMethods, CopyConstructor) {
2928 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2929}
2930
2931TEST_P(ImportImplicitMethods, MoveConstructor) {
2932 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2933}
2934
2935TEST_P(ImportImplicitMethods, Destructor) {
2936 testImportOf(cxxDestructorDecl());
2937}
2938
2939TEST_P(ImportImplicitMethods, CopyAssignment) {
2940 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2941}
2942
2943TEST_P(ImportImplicitMethods, MoveAssignment) {
2944 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2945}
2946
2947TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2948 auto Code = R"(
2949 struct A { A() { int x; } };
2950 )";
2951 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2952}
2953
2954TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2955 auto Code = R"(
2956 struct A { A() = default; };
2957 )";
2958 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2959}
2960
2961TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2962 auto Code = R"(
2963 struct A { A() = delete; };
2964 )";
2965 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2966}
2967
2968TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2969 auto Code = R"(
2970 struct A { void f() { } };
2971 )";
2972 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2973}
2974
2975TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
2976 Decl *ToR1;
2977 {
2978 Decl *FromTU = getTuDecl("struct A { };", Lang_CXX03, "input0.cc");
2979 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2980 FromTU, cxxRecordDecl(hasName("A")));
2981
2982 ToR1 = Import(FromR, Lang_CXX03);
2983 }
2984
2985 Decl *ToR2;
2986 {
2987 Decl *FromTU = getTuDecl("struct A { };", Lang_CXX03, "input1.cc");
2988 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2989 FromTU, cxxRecordDecl(hasName("A")));
2990
2991 ToR2 = Import(FromR, Lang_CXX03);
2992 }
2993
2994 EXPECT_EQ(ToR1, ToR2);
2995}
2996
2997TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
2998 Decl *ToR1;
2999 {
3000 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");
3001 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3002 FromTU, cxxRecordDecl(hasName("A")));
3003 ToR1 = Import(FromR, Lang_CXX03);
3004 }
3005 Decl *ToR2;
3006 {
3007 Decl *FromTU =
3008 getTuDecl("struct A { unsigned x; };", Lang_CXX03, "input1.cc");
3009 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3010 FromTU, cxxRecordDecl(hasName("A")));
3011 ToR2 = Import(FromR, Lang_CXX03);
3012 }
3013 EXPECT_NE(ToR1, ToR2);
3014}
3015
3016TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
3017 Decl *ToF1;
3018 {
3019 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");
3020 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3021 FromTU, fieldDecl(hasName("x")));
3022 ToF1 = Import(FromF, Lang_CXX03);
3023 }
3024 Decl *ToF2;
3025 {
3026 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input1.cc");
3027 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3028 FromTU, fieldDecl(hasName("x")));
3029 ToF2 = Import(FromF, Lang_CXX03);
3030 }
3031 EXPECT_EQ(ToF1, ToF2);
3032}
3033
3034TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
3035 Decl *ToF1;
3036 {
3037 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");
3038 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3039 FromTU, fieldDecl(hasName("x")));
3040 ToF1 = Import(FromF, Lang_CXX03);
3041 }
3042 Decl *ToF2;
3043 {
3044 Decl *FromTU =
3045 getTuDecl("struct A { unsigned x; };", Lang_CXX03, "input1.cc");
3046 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3047 FromTU, fieldDecl(hasName("x")));
3048 ToF2 = Import(FromF, Lang_CXX03);
3049 }
3050 EXPECT_NE(ToF1, ToF2);
3051}
3052
3053TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
3054 Decl *ToM1;
3055 {
3056 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",
3057 Lang_CXX03, "input0.cc");
3058 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3059 FromTU, functionDecl(hasName("x"), isDefinition()));
3060 ToM1 = Import(FromM, Lang_CXX03);
3061 }
3062 Decl *ToM2;
3063 {
3064 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",
3065 Lang_CXX03, "input1.cc");
3066 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3067 FromTU, functionDecl(hasName("x"), isDefinition()));
3068 ToM2 = Import(FromM, Lang_CXX03);
3069 }
3070 EXPECT_EQ(ToM1, ToM2);
3071}
3072
3073TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
3074 Decl *ToM1;
3075 {
3076 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",
3077 Lang_CXX03, "input0.cc");
3078 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3079 FromTU, functionDecl(hasName("x"), isDefinition()));
3080 ToM1 = Import(FromM, Lang_CXX03);
3081 }
3082 Decl *ToM2;
3083 {
3084 Decl *FromTU =
3085 getTuDecl("struct A { void x() const; }; void A::x() const { }",
3086 Lang_CXX03, "input1.cc");
3087 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3088 FromTU, functionDecl(hasName("x"), isDefinition()));
3089 ToM2 = Import(FromM, Lang_CXX03);
3090 }
3091 EXPECT_NE(ToM1, ToM2);
3092}
3093
3094TEST_P(ASTImporterOptionSpecificTestBase,
3095 ImportUnnamedStructsWithRecursingField) {
3096 Decl *FromTU = getTuDecl(
3097 R"(
3098 struct A {
3099 struct {
3100 struct A *next;
3101 } entry0;
3102 struct {
3103 struct A *next;
3104 } entry1;
3105 };
3106 )",
3107 Lang_C99, "input0.cc");
3108 auto *From =
3109 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3110
3111 Import(From, Lang_C99);
3112
3113 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3114 auto *Entry0 =
3115 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3116 auto *Entry1 =
3117 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3118 auto *R0 = getRecordDecl(Entry0);
3119 auto *R1 = getRecordDecl(Entry1);
3120 EXPECT_NE(R0, R1);
3121 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3122 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3123 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3124 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3125}
3126
3127TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
3128 Decl *FromTU = getTuDecl(
3129 R"(
3130 void f(int X, int Y, bool Z) {
3131 (void)[X, Y, Z] { (void)Z; };
3132 }
3133 )",
3134 Lang_CXX11, "input0.cc");
3135 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3136 FromTU, functionDecl(hasName("f")));
3137 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3138 EXPECT_TRUE(ToF);
3139
3140 CXXRecordDecl *FromLambda =
3141 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3142 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3143
3144 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3145 EXPECT_TRUE(ToLambda);
3146
3147 // Check if the fields of the lambda class are imported in correct order.
3148 unsigned FromIndex = 0u;
3149 for (auto *FromField : FromLambda->fields()) {
3150 ASSERT_FALSE(FromField->getDeclName());
3151 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3152 EXPECT_TRUE(ToField);
3153 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3154 EXPECT_TRUE(ToIndex);
3155 EXPECT_EQ(*ToIndex, FromIndex);
3156 ++FromIndex;
3157 }
3158
3159 EXPECT_EQ(FromIndex, 3u);
3160}
3161
3162TEST_P(ASTImporterOptionSpecificTestBase,
3163 MergeFieldDeclsOfClassTemplateSpecialization) {
3164 std::string ClassTemplate =
3165 R"(
3166 template <typename T>
3167 struct X {
3168 int a{0}; // FieldDecl with InitListExpr
3169 X(char) : a(3) {} // (1)
3170 X(int) {} // (2)
3171 };
3172 )";
3173 Decl *ToTU = getToTuDecl(ClassTemplate +
3174 R"(
3175 void foo() {
3176 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3177 X<char> xc('c');
3178 }
3179 )", Lang_CXX11);
3180 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3181 ToTU, classTemplateSpecializationDecl(hasName("X")));
3182 // FieldDecl without InitlistExpr:
3183 auto *ToField = *ToSpec->field_begin();
3184 ASSERT_TRUE(ToField);
3185 ASSERT_FALSE(ToField->getInClassInitializer());
3186 Decl *FromTU = getTuDecl(ClassTemplate +
3187 R"(
3188 void bar() {
3189 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3190 X<char> xc(1);
3191 }
3192 )", Lang_CXX11);
3193 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3194 FromTU, classTemplateSpecializationDecl(hasName("X")));
3195 // FieldDecl with InitlistExpr:
3196 auto *FromField = *FromSpec->field_begin();
3197 ASSERT_TRUE(FromField);
3198 ASSERT_TRUE(FromField->getInClassInitializer());
3199
3200 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3201 ASSERT_TRUE(ImportedSpec);
3202 EXPECT_EQ(ImportedSpec, ToSpec);
3203 // After the import, the FieldDecl has to be merged, thus it should have the
3204 // InitListExpr.
3205 EXPECT_TRUE(ToField->getInClassInitializer());
3206}
3207
3208TEST_P(ASTImporterOptionSpecificTestBase,
3209 MergeFunctionOfClassTemplateSpecialization) {
3210 std::string ClassTemplate =
3211 R"(
3212 template <typename T>
3213 struct X {
3214 void f() {}
3215 void g() {}
3216 };
3217 )";
3218 Decl *ToTU = getToTuDecl(ClassTemplate +
3219 R"(
3220 void foo() {
3221 X<char> x;
3222 x.f();
3223 }
3224 )", Lang_CXX11);
3225 Decl *FromTU = getTuDecl(ClassTemplate +
3226 R"(
3227 void bar() {
3228 X<char> x;
3229 x.g();
3230 }
3231 )", Lang_CXX11);
3232 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3233 FromTU, classTemplateSpecializationDecl(hasName("X")));
3234 auto FunPattern = functionDecl(hasName("g"),
3235 hasParent(classTemplateSpecializationDecl()));
3236 auto *FromFun =
3237 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3238 auto *ToFun =
3239 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3240 ASSERT_TRUE(FromFun->hasBody());
3241 ASSERT_FALSE(ToFun->hasBody());
3242 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3243 ASSERT_TRUE(ImportedSpec);
3244 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3245 ToTU, classTemplateSpecializationDecl(hasName("X")));
3246 EXPECT_EQ(ImportedSpec, ToSpec);
3247 EXPECT_TRUE(ToFun->hasBody());
3248}
3249
3250TEST_P(ASTImporterOptionSpecificTestBase, MergeTemplateSpecWithForwardDecl) {
3251 std::string ClassTemplate =
3252 R"(
3253 template<typename T>
3254 struct X { int m; };
3255 template<>
3256 struct X<int> { int m; };
3257 )";
3258 // Append a forward decl for our template specialization.
3259 getToTuDecl(ClassTemplate + "template<> struct X<int>;", Lang_CXX11);
3260 Decl *FromTU = getTuDecl(ClassTemplate, Lang_CXX11);
3261 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3262 FromTU, classTemplateSpecializationDecl(hasName("X"), isDefinition()));
3263 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3264 // Check that our definition got merged with the existing definition.
3265 EXPECT_TRUE(FromSpec->isThisDeclarationADefinition());
3266 EXPECT_TRUE(ImportedSpec->isThisDeclarationADefinition());
3267}
3268
3269TEST_P(ASTImporterOptionSpecificTestBase,
3270 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3271 std::string ClassTemplate =
3272 R"(
3273 template <typename T>
3274 struct X {};
3275 )";
3276 Decl *ToTU = getToTuDecl(ClassTemplate +
3277 R"(
3278 template <>
3279 struct X<char> {
3280 int a;
3281 };
3282 void foo() {
3283 X<char> x;
3284 }
3285 )",
3286 Lang_CXX11);
3287 Decl *FromTU = getTuDecl(ClassTemplate +
3288 R"(
3289 template <>
3290 struct X<char> {
3291 int b;
3292 };
3293 void foo() {
3294 X<char> x;
3295 }
3296 )",
3297 Lang_CXX11);
3298 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3299 FromTU, classTemplateSpecializationDecl(hasName("X")));
3300 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3301
3302 // We expect one (ODR) warning during the import.
3303 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3304
3305 // The second specialization is different from the first, thus it violates
3306 // ODR, consequently we expect to keep the first specialization only, which is
3307 // already in the "To" context.
3308 EXPECT_FALSE(ImportedSpec);
3309 EXPECT_EQ(1u,
3310 DeclCounter<ClassTemplateSpecializationDecl>().match(
3311 ToTU, classTemplateSpecializationDecl(hasName("X"))));
3312}
3313
3314TEST_P(ASTImporterOptionSpecificTestBase,
3315 MergeCtorOfClassTemplateSpecialization) {
3316 std::string ClassTemplate =
3317 R"(
3318 template <typename T>
3319 struct X {
3320 X(char) {}
3321 X(int) {}
3322 };
3323 )";
3324 Decl *ToTU = getToTuDecl(ClassTemplate +
3325 R"(
3326 void foo() {
3327 X<char> x('c');
3328 }
3329 )", Lang_CXX11);
3330 Decl *FromTU = getTuDecl(ClassTemplate +
3331 R"(
3332 void bar() {
3333 X<char> x(1);
3334 }
3335 )", Lang_CXX11);
3336 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3337 FromTU, classTemplateSpecializationDecl(hasName("X")));
3338 // Match the void(int) ctor.
3339 auto CtorPattern =
3340 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3341 hasParent(classTemplateSpecializationDecl()));
3342 auto *FromCtor =
3343 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3344 auto *ToCtor =
3345 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3346 ASSERT_TRUE(FromCtor->hasBody());
3347 ASSERT_FALSE(ToCtor->hasBody());
3348 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3349 ASSERT_TRUE(ImportedSpec);
3350 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3351 ToTU, classTemplateSpecializationDecl(hasName("X")));
3352 EXPECT_EQ(ImportedSpec, ToSpec);
3353 EXPECT_TRUE(ToCtor->hasBody());
3354}
3355
3356TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateFriendDecl) {
3357 const auto *Code =
3358 R"(
3359 template <class T> class X { friend T; };
3360 struct Y {};
3361 template class X<Y>;
3362 )";
3363 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3364 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3365 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3366 FromTU, classTemplateSpecializationDecl());
3367 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3368 ToTU, classTemplateSpecializationDecl());
3369
3370 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3371 EXPECT_EQ(ImportedSpec, ToSpec);
3372 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3373 ToTU, classTemplateSpecializationDecl()));
3374}
3375
3376TEST_P(ASTImporterOptionSpecificTestBase,
3377 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3378 auto Code =
3379 R"(
3380 // primary template
3381 template<class T1, class T2, int I>
3382 class A {};
3383
3384 // partial specialization
3385 template<class T, int I>
3386 class A<T, T*, I> {};
3387 )";
3388 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3389 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3390 auto *FromSpec =
3391 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3392 FromTU, classTemplatePartialSpecializationDecl());
3393 auto *ToSpec =
3394 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3395 ToTU, classTemplatePartialSpecializationDecl());
3396
3397 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3398 EXPECT_EQ(ImportedSpec, ToSpec);
3399 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3400 ToTU, classTemplatePartialSpecializationDecl()));
3401}
3402
3403TEST_P(ASTImporterOptionSpecificTestBase,
3404 ClassTemplateSpecializationsShouldNotBeDuplicated) {
3405 auto Code =
3406 R"(
3407 // primary template
3408 template<class T1, class T2, int I>
3409 class A {};
3410
3411 // full specialization
3412 template<>
3413 class A<int, int, 1> {};
3414 )";
3415 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3416 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3417 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3418 FromTU, classTemplateSpecializationDecl());
3419 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3420 ToTU, classTemplateSpecializationDecl());
3421
3422 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3423 EXPECT_EQ(ImportedSpec, ToSpec);
3424 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3425 ToTU, classTemplateSpecializationDecl()));
3426}
3427
3428TEST_P(ASTImporterOptionSpecificTestBase,
3429 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3430 std::string PrimaryTemplate =
3431 R"(
3432 template<class T1, class T2, int I>
3433 class A {};
3434 )";
3435 auto PartialSpec =
3436 R"(
3437 template<class T, int I>
3438 class A<T, T*, I> {};
3439 )";
3440 auto FullSpec =
3441 R"(
3442 template<>
3443 class A<int, int, 1> {};
3444 )";
3445 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3446 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3447 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3448 FromTU, classTemplateSpecializationDecl());
3449
3450 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3451 EXPECT_TRUE(ImportedSpec);
3452 // Check the number of partial specializations.
3453 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3454 ToTU, classTemplatePartialSpecializationDecl()));
3455 // Check the number of full specializations.
3456 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3457 ToTU, classTemplateSpecializationDecl(
3458 unless(classTemplatePartialSpecializationDecl()))));
3459}
3460
3461TEST_P(ASTImporterOptionSpecificTestBase,
3462 InitListExprValueKindShouldBeImported) {
3463 Decl *TU = getTuDecl(
3464 R"(
3465 const int &init();
3466 void foo() { const int &a{init()}; }
3467 )", Lang_CXX11, "input0.cc");
3468 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3469 ASSERT_TRUE(FromD->getAnyInitializer());
3470 auto *InitExpr = FromD->getAnyInitializer();
3471 ASSERT_TRUE(InitExpr);
3472 ASSERT_TRUE(InitExpr->isGLValue());
3473
3474 auto *ToD = Import(FromD, Lang_CXX11);
3475 EXPECT_TRUE(ToD);
3476 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3477 EXPECT_TRUE(ToInitExpr);
3478 EXPECT_TRUE(ToInitExpr->isGLValue());
3479}
3480
3481struct ImportVariables : ASTImporterOptionSpecificTestBase {};
3482
3483TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3484 Decl *FromTU = getTuDecl(
3485 R"(
3486 struct A {
3487 static const int a = 1 + 2;
3488 };
3489 const int A::a;
3490 )",
3491 Lang_CXX03, "input1.cc");
3492
3493 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3494 FromTU, varDecl(hasName("a"))); // Decl with init
3495 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3496 FromTU, varDecl(hasName("a"))); // Decl with definition
3497 ASSERT_NE(FromDWithInit, FromDWithDef);
3498 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3499
3500 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3501 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3502 ASSERT_TRUE(ToD0);
3503 ASSERT_TRUE(ToD1);
3504 EXPECT_NE(ToD0, ToD1);
3505 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3506}
3507
3508TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3509 auto StructA =
3510 R"(
3511 struct A {
3512 static const int a = 1 + 2;
3513 };
3514 )";
3515 Decl *ToTU = getToTuDecl(StructA, Lang_CXX03);
3516 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX03,
3517 "input1.cc");
3518
3519 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3520 FromTU, varDecl(hasName("a"))); // Decl with init
3521 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3522 FromTU, varDecl(hasName("a"))); // Decl with definition
3523 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3524 ASSERT_TRUE(FromDWithInit->getInit());
3525 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3526 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3527 ASSERT_FALSE(FromDWithDef->getInit());
3528
3529 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3530 ToTU, varDecl(hasName("a"))); // Decl with init
3531 ASSERT_TRUE(ToD->getInit());
3532 ASSERT_FALSE(ToD->getDefinition());
3533
3534 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3535 EXPECT_TRUE(ImportedD->getAnyInitializer());
3536 EXPECT_TRUE(ImportedD->getDefinition());
3537}
3538
3539TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3540 auto StructA =
3541 R"(
3542 struct A {
3543 static const int a;
3544 };
3545 )";
3546 Decl *ToTU = getToTuDecl(StructA, Lang_CXX03);
3547 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3548 Lang_CXX03, "input1.cc");
3549
3550 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3551 FromTU, varDecl(hasName("a")));
3552 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3553 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3554 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3555 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3556 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3557 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3558 ASSERT_TRUE(FromDWithDef->getInit());
3559
3560 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3561 ToTU, varDecl(hasName("a")));
3562 ASSERT_FALSE(ToD->getInit());
3563 ASSERT_FALSE(ToD->getDefinition());
3564
3565 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3566 EXPECT_TRUE(ImportedD->getAnyInitializer());
3567 EXPECT_TRUE(ImportedD->getDefinition());
3568}
3569
3570struct ImportClasses : ASTImporterOptionSpecificTestBase {};
3571
3572TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3573 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C99);
3574 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C99, "input1.cc");
3575 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3576 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3577 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3578
3579 Decl *ImportedDef = Import(FromDef, Lang_C99);
3580
3581 EXPECT_NE(ImportedDef, ToProto);
3582 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3583 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3584 EXPECT_TRUE(ImportedDef == ToDef);
3585 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3586 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3587 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3588}
3589
3590TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3591 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX03);
3592 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX03, "input1.cc");
3593 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3594 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3595 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3596
3597 Decl *ImportedDef = Import(FromDef, Lang_CXX03);
3598
3599 EXPECT_NE(ImportedDef, ToProto);
3600 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3601 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3602 EXPECT_TRUE(ImportedDef == ToDef);
3603 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3604 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3605 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3606}
3607
3608TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3609 Decl *FromTU0 =
3610 getTuDecl("struct A { struct X *Xp; };", Lang_C99, "input0.cc");
3611 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C99, "input1.cc");
3612 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3613 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3614 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3615
3616 Decl *ImportedProto = Import(FromProto, Lang_C99);
3617 Decl *ImportedDef = Import(FromDef, Lang_C99);
3618 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3619
3620 EXPECT_NE(ImportedDef, ImportedProto);
3621 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3622 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3623 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3624 EXPECT_TRUE(ImportedDef == ToDef);
3625 EXPECT_TRUE(ImportedProto == ToProto);
3626 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3627 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3628 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3629}
3630
3631
3632struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
3633
3634TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3635 Decl *FromTU = getTuDecl(
3636 R"(
3637 class A {
3638 template <int I> class F {};
3639 class X {
3640 template <int I> friend class F;
3641 };
3642 };
3643 )",
3644 Lang_CXX03, "input0.cc");
3645
3646 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3647 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3648 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3649 FromTU, cxxRecordDecl(hasName("F")));
3650
3651 ASSERT_TRUE(FromClass);
3652 ASSERT_TRUE(FromFriendClass);
3653 ASSERT_NE(FromClass, FromFriendClass);
3654 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3655 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3656 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3657 FromClass->getDescribedClassTemplate());
3658
3659 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX03));
3660 auto *ToFriendClass =
3661 cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX03));
3662
3663 EXPECT_TRUE(ToClass);
3664 EXPECT_TRUE(ToFriendClass);
3665 EXPECT_NE(ToClass, ToFriendClass);
3666 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3667 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3668 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3669 ToClass->getDescribedClassTemplate());
3670}
3671
3672TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3673 Decl *FromTu = getTuDecl(
3674 R"(
3675 class declToImport {
3676 friend class declToImport;
3677 };
3678 )",
3679 Lang_CXX03, "input.cc");
3680
3681 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3682 FromTu, cxxRecordDecl(hasName("declToImport")));
3683 auto *ToD = Import(FromD, Lang_CXX03);
3684 auto Pattern = cxxRecordDecl(has(friendDecl()));
3685 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3686 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3687}
3688
3689TEST_P(ImportFriendClasses, UndeclaredFriendClassShouldNotBeVisible) {
3690 Decl *FromTu =
3691 getTuDecl("class X { friend class Y; };", Lang_CXX03, "from.cc");
3692 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
3693 FromTu, cxxRecordDecl(hasName("X")));
3694 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3695 RecordDecl *FromRecordOfFriend =
3696 const_cast<RecordDecl *>(getRecordDeclOfFriend(FromFriend));
3697
3698 ASSERT_EQ(FromRecordOfFriend->getDeclContext(), cast<DeclContext>(FromTu));
3699 ASSERT_EQ(FromRecordOfFriend->getLexicalDeclContext(),
3700 cast<DeclContext>(FromX));
3701 ASSERT_FALSE(
3702 FromRecordOfFriend->getDeclContext()->containsDecl(FromRecordOfFriend));
3703 ASSERT_FALSE(FromRecordOfFriend->getLexicalDeclContext()->containsDecl(
3704 FromRecordOfFriend));
3705 ASSERT_FALSE(FromRecordOfFriend->getLookupParent()
3706 ->lookup(FromRecordOfFriend->getDeclName())
3707 .empty());
3708
3709 auto *ToX = Import(FromX, Lang_CXX03);
3710 ASSERT_TRUE(ToX);
3711
3712 Decl *ToTu = ToX->getTranslationUnitDecl();
3713 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3714 RecordDecl *ToRecordOfFriend =
3715 const_cast<RecordDecl *>(getRecordDeclOfFriend(ToFriend));
3716
3717 ASSERT_EQ(ToRecordOfFriend->getDeclContext(), cast<DeclContext>(ToTu));
3718 ASSERT_EQ(ToRecordOfFriend->getLexicalDeclContext(), cast<DeclContext>(ToX));
3719 EXPECT_FALSE(
3720 ToRecordOfFriend->getDeclContext()->containsDecl(ToRecordOfFriend));
3721 EXPECT_FALSE(ToRecordOfFriend->getLexicalDeclContext()->containsDecl(
3722 ToRecordOfFriend));
3723 EXPECT_FALSE(ToRecordOfFriend->getLookupParent()
3724 ->lookup(ToRecordOfFriend->getDeclName())
3725 .empty());
3726}
3727
3728TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3729 Decl *FromTu = getTuDecl(
3730 R"(
3731 template<class A> class declToImport {
3732 template<class A1> friend class declToImport;
3733 };
3734 )",
3735 Lang_CXX03, "input.cc");
3736
3737 auto *FromD =
3738 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3739 auto *ToD = Import(FromD, Lang_CXX03);
3740
3741 auto Pattern = classTemplateDecl(
3742 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3743 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3744 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3745
3746 auto *Class =
3747 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3748 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3749 EXPECT_NE(Friend->getFriendDecl(), Class);
3750 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3751}
3752
3753TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3754 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3755
3756 ClassTemplateSpecializationDecl *Imported1;
3757 {
3758 Decl *FromTU = getTuDecl("template<class T> class X;"
3759 "struct Y { friend class X<int>; };",
3760 Lang_CXX03, "input0.cc");
3761 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3762 FromTU, Pattern);
3763
3764 Imported1 =
3765 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));
3766 }
3767 ClassTemplateSpecializationDecl *Imported2;
3768 {
3769 Decl *FromTU = getTuDecl("template<class T> class X;"
3770 "template<> class X<int>{};"
3771 "struct Z { friend class X<int>; };",
3772 Lang_CXX03, "input1.cc");
3773 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3774 FromTU, Pattern);
3775
3776 Imported2 =
3777 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));
3778 }
3779
3780 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3781 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3782 2u);
3783 ASSERT_TRUE(Imported2->getPreviousDecl());
3784 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3785}
3786
3787TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3788 Decl *FromTU0 = getTuDecl(
3789 R"(
3790 class X {
3791 class Y;
3792 };
3793 class X::Y {
3794 template <typename T>
3795 friend class F; // The decl context of F is the global namespace.
3796 };
3797 )",
3798 Lang_CXX03, "input0.cc");
3799 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3800 FromTU0, classTemplateDecl(hasName("F")));
3801 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));
3802 Decl *FromTU1 = getTuDecl(
3803 R"(
3804 template <typename T>
3805 class F {};
3806 )",
3807 Lang_CXX03, "input1.cc");
3808 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3809 FromTU1, classTemplateDecl(hasName("F")));
3810 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
3811 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3812 Imported1->getTemplatedDecl()->getTypeForDecl());
3813}
3814
3815TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3816 Decl *From, *To;
3817 std::tie(From, To) =
3818 getImportedDecl("class declToImport {};", Lang_CXX03,
3819 "class Y { friend class declToImport; };", Lang_CXX03);
3820 auto *Imported = cast<CXXRecordDecl>(To);
3821
3822 EXPECT_TRUE(Imported->getPreviousDecl());
3823}
3824
3825TEST_P(ImportFriendClasses,
3826 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3827 Decl *ToTU = getToTuDecl(
3828 R"(
3829 class X {
3830 class Y;
3831 };
3832 class X::Y {
3833 template <typename T>
3834 friend class F; // The decl context of F is the global namespace.
3835 };
3836 )",
3837 Lang_CXX03);
3838 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3839 ToTU, classTemplateDecl(hasName("F")));
3840 Decl *FromTU = getTuDecl(
3841 R"(
3842 template <typename T>
3843 class F {};
3844 )",
3845 Lang_CXX03, "input0.cc");
3846 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3847 FromTU, classTemplateDecl(hasName("F")));
3848 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
3849 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3850 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3851 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3852 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3853}
3854
3855TEST_P(ImportFriendClasses,
3856 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3857 Decl *FromTU0 = getTuDecl(
3858 R"(
3859 class X {
3860 class Y;
3861 };
3862 class X::Y {
3863 template <typename T>
3864 friend class F; // The decl context of F is the global namespace.
3865 };
3866 )",
3867 Lang_CXX03, "input0.cc");
3868 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3869 FromTU0, classTemplateDecl(hasName("F")));
3870 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));
3871 Decl *FromTU1 = getTuDecl(
3872 R"(
3873 template <typename T>
3874 class F {};
3875 )",
3876 Lang_CXX03, "input1.cc");
3877 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3878 FromTU1, classTemplateDecl(hasName("F")));
3879 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
3880 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3881 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3882 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3883 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3884}
3885
3886TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3887 Decl *FromTU0 = getTuDecl(
3888 R"(
3889 class X {
3890 class Y;
3891 };
3892 class X::Y {
3893 friend class F; // The decl context of F is the global namespace.
3894 };
3895 )",
3896 Lang_CXX03, "input0.cc");
3897 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3898 QualType FT = Friend->getFriendType()->getType();
3899 FT = FromTU0->getASTContext().getCanonicalType(FT);
3900 auto *Fwd = cast<TagType>(FT)->getDecl();
3901 auto *ImportedFwd = Import(Fwd, Lang_CXX03);
3902 Decl *FromTU1 = getTuDecl(
3903 R"(
3904 class F {};
3905 )",
3906 Lang_CXX03, "input1.cc");
3907 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
3908 FromTU1, cxxRecordDecl(hasName("F")));
3909 auto *ImportedDef = Import(Definition, Lang_CXX03);
3910 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3911 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3912}
3913
3914TEST_P(ImportFriendClasses, ImportOfRepeatedFriendType) {
3915 const char *Code =
3916 R"(
3917 class Container {
3918 friend class X;
3919 friend class X;
3920 };
3921 )";
3922 Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
3923 Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
3924
3925 auto *ToFriend1 = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3926 auto *ToFriend2 = LastDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3927 auto *FromFriend1 =
3928 FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3929 auto *FromFriend2 = LastDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3930
3931 FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
3932 FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
3933
3934 EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
3935 EXPECT_EQ(ToFriend1, ToImportedFriend1);
3936 EXPECT_EQ(ToFriend2, ToImportedFriend2);
3937}
3938
3939TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {
3940 const char *Code =
3941 R"(
3942 class Container {
3943 friend void f();
3944 friend void f();
3945 };
3946 )";
3947 Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
3948 Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
3949
3950 auto *ToFriend1 = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3951 auto *ToFriend2 = LastDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3952 auto *FromFriend1 =
3953 FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3954 auto *FromFriend2 = LastDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3955
3956 FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
3957 FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
3958
3959 EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
3960 EXPECT_EQ(ToFriend1, ToImportedFriend1);
3961 EXPECT_EQ(ToFriend2, ToImportedFriend2);
3962}
3963
3964TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
3965 auto *Code = R"(
3966 template <class T>
3967 struct X {
3968 friend void foo(){}
3969 };
3970 )";
3971 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);
3972 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
3973 ToTU, functionDecl(hasName("foo")));
3974
3975 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX03, "input.cc");
3976 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
3977 FromTU, functionDecl(hasName("foo")));
3978 auto *ImportedFoo = Import(FromFoo, Lang_CXX03);
3979 EXPECT_EQ(ImportedFoo, ToFoo);
3980}
3981
3982struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
3983
3984TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3985 Decl *TU = getTuDecl(
3986 R"(
3987 namespace NS {
3988
3989 template <typename T>
3990 struct S {};
3991 template struct S<int>;
3992
3993 inline namespace INS {
3994 template <typename T>
3995 struct S {};
3996 template struct S<int>;
3997 }
3998
3999 }
4000 )", Lang_CXX11, "input0.cc");
4001 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4002 TU, namespaceDecl());
4003 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4004 TU, classTemplateSpecializationDecl());
4005 ASSERT_TRUE(NS->containsDecl(Spec));
4006
4007 NS->removeDecl(Spec);
4008 EXPECT_FALSE(NS->containsDecl(Spec));
4009}
4010
4011TEST_P(DeclContextTest,
4012 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4013 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX03);
4014 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4015 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4016
4017 // Investigate the list.
4018 auto *DC = A0->getDeclContext();
4019 ASSERT_TRUE(DC->containsDecl(A0));
4020 ASSERT_TRUE(DC->containsDecl(A1));
4021
4022 // Investigate the lookup table.
4023 auto *Map = DC->getLookupPtr();
4024 ASSERT_TRUE(Map);
4025 auto I = Map->find(A0->getDeclName());
4026 ASSERT_NE(I, Map->end());
4027 StoredDeclsList &L = I->second;
4028 // The lookup table contains the most recent decl of A.
4029 ASSERT_NE(L.getAsDecl(), A0);
4030 ASSERT_EQ(L.getAsDecl(), A1);
4031
4032 ASSERT_TRUE(L.getAsDecl());
4033 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4034 // The point here is to have a Vec with only one element, which is not the
4035 // one we are going to delete from the DC later.
4036 L.setHasExternalDecls();
4037 ASSERT_TRUE(L.getAsVector());
4038 ASSERT_EQ(1u, L.getAsVector()->size());
4039
4040 // This asserts in the old implementation.
4041 DC->removeDecl(A0);
4042 EXPECT_FALSE(DC->containsDecl(A0));
4043}
4044
4045struct ImportFunctionTemplateSpecializations
4046 : ASTImporterOptionSpecificTestBase {};
4047
4048TEST_P(ImportFunctionTemplateSpecializations,
4049 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4050
4051 Decl *FromTU = getTuDecl(
4052 R"(
4053 template<class T>
4054 int f() { return 0; }
4055 void foo() { f<int>(); }
4056 )",
4057 Lang_CXX03, "input0.cc");
4058
4059 // Check that the function template instantiation is NOT the child of the TU.
4060 auto Pattern = translationUnitDecl(
4061 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4062 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4063
4064 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4065 FromTU, functionDecl(hasName("foo")));
4066 ASSERT_TRUE(Import(Foo, Lang_CXX03));
4067
4068 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4069 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4070}
4071
4072TEST_P(ImportFunctionTemplateSpecializations,
4073 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4074
4075 Decl *FromTU = getTuDecl(
4076 R"(
4077 template<class T>
4078 int f() { return 0; }
4079 template int f<int>();
4080 )",
4081 Lang_CXX03, "input0.cc");
4082
4083 // Check that the function template instantiation is NOT the child of the TU.
4084 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4085 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4086 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4087
4088 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation),
4089 Lang_CXX03));
4090
4091 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4092 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4093}
4094
4095TEST_P(ImportFunctionTemplateSpecializations,
4096 TUshouldContainFunctionTemplateSpecialization) {
4097
4098 Decl *FromTU = getTuDecl(
4099 R"(
4100 template<class T>
4101 int f() { return 0; }
4102 template <> int f<int>() { return 4; }
4103 )",
4104 Lang_CXX03, "input0.cc");
4105
4106 // Check that the function template specialization is the child of the TU.
4107 auto Specialization =
4108 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4109 auto Pattern = translationUnitDecl(has(Specialization));
4110 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4111
4112 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization),
4113 Lang_CXX03));
4114
4115 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4116 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4117}
4118
4119TEST_P(ImportFunctionTemplateSpecializations,
4120 FunctionTemplateSpecializationRedeclChain) {
4121
4122 Decl *FromTU = getTuDecl(
4123 R"(
4124 template<class T>
4125 int f() { return 0; }
4126 template <> int f<int>() { return 4; }
4127 )",
4128 Lang_CXX03, "input0.cc");
4129
4130 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4131 hasParent(translationUnitDecl()));
4132 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4133 {
4134 auto *TU = FromTU;
4135 auto *SpecD = FromSpecD;
4136 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4137 TU, functionTemplateDecl());
4138 auto *FirstSpecD = *(TemplateD->spec_begin());
4139 ASSERT_EQ(SpecD, FirstSpecD);
4140 ASSERT_TRUE(SpecD->getPreviousDecl());
4141 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4142 ->doesThisDeclarationHaveABody());
4143 }
4144
4145 ASSERT_TRUE(Import(FromSpecD, Lang_CXX03));
4146
4147 {
4148 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4149 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4150 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4151 TU, functionTemplateDecl());
4152 auto *FirstSpecD = *(TemplateD->spec_begin());
4153 EXPECT_EQ(SpecD, FirstSpecD);
4154 ASSERT_TRUE(SpecD->getPreviousDecl());
4155 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4156 ->doesThisDeclarationHaveABody());
4157 }
4158}
4159
4160TEST_P(ImportFunctionTemplateSpecializations,
4161 MatchNumberOfFunctionTemplateSpecializations) {
4162
4163 Decl *FromTU = getTuDecl(
4164 R"(
4165 template <typename T> constexpr int f() { return 0; }
4166 template <> constexpr int f<int>() { return 4; }
4167 void foo() {
4168 static_assert(f<char>() == 0, "");
4169 static_assert(f<int>() == 4, "");
4170 }
4171 )",
4172 Lang_CXX11, "input0.cc");
4173 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4174 FromTU, functionDecl(hasName("foo")));
4175
4176 Import(FromD, Lang_CXX11);
4177 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4178 EXPECT_EQ(
4179 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4180 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4181}
4182
4183TEST_P(ASTImporterOptionSpecificTestBase,
4184 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4185 {
4186 Decl *FromTU = getTuDecl(
4187 R"(
4188 template <typename T>
4189 struct B;
4190 )",
4191 Lang_CXX03, "input0.cc");
4192 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4193 FromTU, classTemplateDecl(hasName("B")));
4194
4195 Import(FromD, Lang_CXX03);
4196 }
4197
4198 {
4199 Decl *FromTU = getTuDecl(
4200 R"(
4201 template <typename T>
4202 struct B {
4203 void f();
4204 B* b;
4205 };
4206 )",
4207 Lang_CXX03, "input1.cc");
4208 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4209 FromTU, functionDecl(hasName("f")));
4210 Import(FromD, Lang_CXX03);
4211 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4212 FromTU, classTemplateDecl(hasName("B")));
4213 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));
4214 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4215
4216 // We expect no (ODR) warning during the import.
4217 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4218 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4219 }
4220}
4221
4222TEST_P(ASTImporterOptionSpecificTestBase,
4223 ImportingTypedefShouldImportTheCompleteType) {
4224 // We already have an incomplete underlying type in the "To" context.
4225 auto Code =
4226 R"(
4227 template <typename T>
4228 struct S {
4229 void foo();
4230 };
4231 using U = S<int>;
4232 )";
4233 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4234 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4235 typedefNameDecl(hasName("U")));
4236 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4237
4238 // The "From" context has the same typedef, but the underlying type is
4239 // complete this time.
4240 Decl *FromTU = getTuDecl(std::string(Code) +
4241 R"(
4242 void foo(U* u) {
4243 u->foo();
4244 }
4245 )", Lang_CXX11);
4246 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4247 typedefNameDecl(hasName("U")));
4248 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4249
4250 // The imported type should be complete.
4251 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4252 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4253}
4254
4255TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
4256 auto Code =
4257 R"(
4258 template<class T>
4259 int f() { return 0; }
4260 template <> int f<int>() { return 4; }
4261 )";
4262
4263 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
4264 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
4265 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
4266 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
4267
4268 auto *ToD = Import(FromD, Lang_CXX03);
4269 // The template parameter list should exist.
4270 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
4271}
4272
4273struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
4274
4275TEST_P(ASTImporterLookupTableTest, OneDecl) {
4276 auto *ToTU = getToTuDecl("int a;", Lang_CXX03);
4277 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4278 ASTImporterLookupTable LT(*ToTU);
4279 auto Res = LT.lookup(ToTU, D->getDeclName());
4280 ASSERT_EQ(Res.size(), 1u);
4281 EXPECT_EQ(*Res.begin(), D);
4282}
4283
4284static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4285 for (Decl *D : DC->decls()) {
4286 if (auto *ND = dyn_cast<NamedDecl>(D))
4287 if (ND->getDeclName() == Name)
4288 return ND;
4289 }
4290 return nullptr;
4291}
4292
4293TEST_P(ASTImporterLookupTableTest,
4294 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4295 auto *Code = R"(
4296 template <class T>
4297 struct X {
4298 friend void foo(){}
4299 };
4300 )";
4301 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);
4302 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4303 ToTU, classTemplateDecl(hasName("X")));
4304 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4305 ToTU, functionDecl(hasName("foo")));
4306 DeclContext *FooDC = Foo->getDeclContext();
4307 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4308 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4309 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4310 DeclarationName FooName = Foo->getDeclName();
4311
4312 // Cannot find in the LookupTable of its DC (TUDecl)
4313 SmallVector<NamedDecl *, 2> FoundDecls;
4314 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4315 EXPECT_EQ(FoundDecls.size(), 0u);
4316
4317 // Cannot find in the LookupTable of its LexicalDC (X)
4318 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4319 EXPECT_EQ(FoundDecls.size(), 0u);
4320
4321 // Can't find in the list of Decls of the DC.
4322 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4323
4324 // Can't find in the list of Decls of the LexicalDC
4325 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4326
4327 // ASTImporter specific lookup finds it.
4328 ASTImporterLookupTable LT(*ToTU);
4329 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4330 ASSERT_EQ(Res.size(), 1u);
4331 EXPECT_EQ(*Res.begin(), Foo);
4332}
4333
4334TEST_P(ASTImporterLookupTableTest,
4335 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4336 TranslationUnitDecl *ToTU =
4337 getToTuDecl("struct A { struct Foo *p; };", Lang_C99);
4338 auto *Foo =
4339 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4340 auto *A =
4341 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4342 DeclContext *FooDC = Foo->getDeclContext();
4343 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4344 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4345 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4346 DeclarationName FooName = Foo->getDeclName();
4347
4348 // Cannot find in the LookupTable of its DC (TUDecl).
4349 SmallVector<NamedDecl *, 2> FoundDecls;
4350 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4351 EXPECT_EQ(FoundDecls.size(), 0u);
4352
4353 // Cannot find in the LookupTable of its LexicalDC (A).
4354 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4355 EXPECT_EQ(FoundDecls.size(), 0u);
4356
4357 // Can't find in the list of Decls of the DC.
4358 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4359
4360 // Can find in the list of Decls of the LexicalDC.
4361 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4362
4363 // ASTImporter specific lookup finds it.
4364 ASTImporterLookupTable LT(*ToTU);
4365 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4366 ASSERT_EQ(Res.size(), 1u);
4367 EXPECT_EQ(*Res.begin(), Foo);
4368}
4369
4370TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4371 TranslationUnitDecl *ToTU =
4372 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C99);
4373 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4374 .match(ToTU, varDecl(hasName("V")))
4375 ->getDeclName();
4376 auto *A =
4377 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4378 auto *B =
4379 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4380
4381 ASTImporterLookupTable LT(*ToTU);
4382
4383 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4384 ASSERT_EQ(Res.size(), 1u);
4385 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4386 ToTU, fieldDecl(hasName("V"),
4387 hasParent(recordDecl(hasName("A"))))));
4388 Res = LT.lookup(cast<DeclContext>(B), VName);
4389 ASSERT_EQ(Res.size(), 1u);
4390 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4391 ToTU, fieldDecl(hasName("V"),
4392 hasParent(recordDecl(hasName("B"))))));
4393 Res = LT.lookup(ToTU, VName);
4394 ASSERT_EQ(Res.size(), 1u);
4395 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4396 ToTU, varDecl(hasName("V"),
4397 hasParent(translationUnitDecl()))));
4398}
4399
4400TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4401 TranslationUnitDecl *ToTU = getToTuDecl(
4402 R"(
4403 void foo();
4404 void foo(int);
4405 void foo(int, int);
4406 )",
4407 Lang_CXX03);
4408
4409 ASTImporterLookupTable LT(*ToTU);
4410 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4411 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4412 DeclarationName Name = F0->getDeclName();
4413 auto Res = LT.lookup(ToTU, Name);
4414 EXPECT_EQ(Res.size(), 3u);
4415 EXPECT_EQ(Res.count(F0), 1u);
4416 EXPECT_EQ(Res.count(F2), 1u);
4417}
4418
4419TEST_P(ASTImporterLookupTableTest,
4420 DifferentOperatorsShouldHaveDifferentResultSet) {
4421 TranslationUnitDecl *ToTU = getToTuDecl(
4422 R"(
4423 struct X{};
4424 void operator+(X, X);
4425 void operator-(X, X);
4426 )",
4427 Lang_CXX03);
4428
4429 ASTImporterLookupTable LT(*ToTU);
4430 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
4431 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4432 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
4433 ToTU, functionDecl(hasOverloadedOperatorName("-")));
4434 DeclarationName NamePlus = FPlus->getDeclName();
4435 auto ResPlus = LT.lookup(ToTU, NamePlus);
4436 EXPECT_EQ(ResPlus.size(), 1u);
4437 EXPECT_EQ(ResPlus.count(FPlus), 1u);
4438 EXPECT_EQ(ResPlus.count(FMinus), 0u);
4439 DeclarationName NameMinus = FMinus->getDeclName();
4440 auto ResMinus = LT.lookup(ToTU, NameMinus);
4441 EXPECT_EQ(ResMinus.size(), 1u);
4442 EXPECT_EQ(ResMinus.count(FMinus), 1u);
4443 EXPECT_EQ(ResMinus.count(FPlus), 0u);
4444 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
4445}
4446
4447TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
4448 TranslationUnitDecl *ToTU = getToTuDecl(
4449 R"(
4450 struct X {};
4451 void operator+(X, X);
4452 )",
4453 Lang_CXX03);
4454 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
4455 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4456
4457 Decl *FromTU = getTuDecl(
4458 R"(
4459 struct X {};
4460 void operator+(X, X);
4461 )",
4462 Lang_CXX03);
4463 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
4464 FromTU, functionDecl(hasOverloadedOperatorName("+")));
4465
4466 // FromPlus have a different TU, thus its DeclarationName is different too.
4467 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
4468
4469 ASTImporterLookupTable LT(*ToTU);
4470 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
4471 ASSERT_EQ(Res.size(), 1u);
4472 EXPECT_EQ(*Res.begin(), ToPlus);
4473
4474 // FromPlus have a different TU, thus its DeclarationName is different too.
4475 Res = LT.lookup(ToTU, FromPlus->getDeclName());
4476 ASSERT_EQ(Res.size(), 0u);
4477}
4478
4479TEST_P(ASTImporterLookupTableTest,
4480 LookupFindsFwdFriendClassDeclWithElaboratedType) {
4481 TranslationUnitDecl *ToTU = getToTuDecl(
4482 R"(
4483 class Y { friend class F; };
4484 )",
4485 Lang_CXX03);
4486
4487 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4488 // So we must dig up the underlying CXXRecordDecl.
4489 ASTImporterLookupTable LT(*ToTU);
4490 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4491 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4492 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4493 ToTU, cxxRecordDecl(hasName("Y")));
4494
4495 DeclarationName Name = RD->getDeclName();
4496 auto Res = LT.lookup(ToTU, Name);
4497 EXPECT_EQ(Res.size(), 1u);
4498 EXPECT_EQ(*Res.begin(), RD);
4499
4500 Res = LT.lookup(Y, Name);
4501 EXPECT_EQ(Res.size(), 0u);
4502}
4503
4504TEST_P(ASTImporterLookupTableTest,
4505 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
4506 TranslationUnitDecl *ToTU = getToTuDecl(
4507 R"(
4508 class F;
4509 class Y { friend F; };
4510 )",
4511 Lang_CXX11);
4512
4513 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4514 // So we must dig up the underlying CXXRecordDecl.
4515 ASTImporterLookupTable LT(*ToTU);
4516 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4517 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4518 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
4519
4520 DeclarationName Name = RD->getDeclName();
4521 auto Res = LT.lookup(ToTU, Name);
4522 EXPECT_EQ(Res.size(), 1u);
4523 EXPECT_EQ(*Res.begin(), RD);
4524
4525 Res = LT.lookup(Y, Name);
4526 EXPECT_EQ(Res.size(), 0u);
4527}
4528
4529TEST_P(ASTImporterLookupTableTest,
4530 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
4531 TranslationUnitDecl *ToTU = getToTuDecl(
4532 R"(
4533 class F;
4534 using alias_of_f = F;
4535 class Y { friend alias_of_f; };
4536 )",
4537 Lang_CXX11);
4538
4539 // ASTImporterLookupTable constructor handles using declarations correctly,
4540 // no assert is expected.
4541 ASTImporterLookupTable LT(*ToTU);
4542
4543 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
4544 ToTU, typeAliasDecl(hasName("alias_of_f")));
4545 DeclarationName Name = Alias->getDeclName();
4546 auto Res = LT.lookup(ToTU, Name);
4547 EXPECT_EQ(Res.count(Alias), 1u);
4548}
4549
4550TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4551 TranslationUnitDecl *ToTU = getToTuDecl(
4552 R"(
4553 class Y { template <class T> friend class F; };
4554 )",
4555 Lang_CXX03);
4556
4557 ASTImporterLookupTable LT(*ToTU);
4558 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4559 ToTU, classTemplateDecl(hasName("F")));
4560 DeclarationName Name = F->getDeclName();
4561 auto Res = LT.lookup(ToTU, Name);
4562 EXPECT_EQ(Res.size(), 2u);
4563 EXPECT_EQ(Res.count(F), 1u);
4564 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4565}
4566
4567TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4568 TranslationUnitDecl *ToTU = getToTuDecl(
4569 R"(
4570 template <typename T>
4571 class F;
4572
4573 template <typename T>
4574 class Y {
4575 friend class F<T>;
4576 };
4577 )",
4578 Lang_CXX03);
4579
4580 ASTImporterLookupTable LT(*ToTU);
4581 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4582 ToTU, classTemplateDecl(hasName("F")));
4583 DeclarationName Name = F->getDeclName();
4584 auto Res = LT.lookup(ToTU, Name);
4585 EXPECT_EQ(Res.size(), 2u);
4586 EXPECT_EQ(Res.count(F), 1u);
4587 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4588}
4589
4590TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4591 TranslationUnitDecl *ToTU = getToTuDecl(
4592 R"(
4593 template <typename T>
4594 class F;
4595
4596 class Y {
4597 friend class F<int>;
4598 };
4599 )",
4600 Lang_CXX03);
4601
4602 ASTImporterLookupTable LT(*ToTU);
4603 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4604 ToTU, classTemplateDecl(hasName("F")));
4605 DeclarationName Name = F->getDeclName();
4606 auto Res = LT.lookup(ToTU, Name);
4607 ASSERT_EQ(Res.size(), 3u);
4608 EXPECT_EQ(Res.count(F), 1u);
4609 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4610 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4611}
4612
4613TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4614 TranslationUnitDecl *ToTU = getToTuDecl(
4615 R"(
4616 class Y { friend void F(); };
4617 )",
4618 Lang_CXX03);
4619
4620 ASTImporterLookupTable LT(*ToTU);
4621 auto *F =
4622 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4623 DeclarationName Name = F->getDeclName();
4624 auto Res = LT.lookup(ToTU, Name);
4625 EXPECT_EQ(Res.size(), 1u);
4626 EXPECT_EQ(*Res.begin(), F);
4627}
4628
4629TEST_P(ASTImporterLookupTableTest,
4630 LookupFindsDeclsInClassTemplateSpecialization) {
4631 TranslationUnitDecl *ToTU = getToTuDecl(
4632 R"(
4633 template <typename T>
4634 struct X {
4635 int F;
4636 };
4637 void foo() {
4638 X<char> xc;
4639 }
4640 )",
4641 Lang_CXX03);
4642
4643 ASTImporterLookupTable LT(*ToTU);
4644
4645 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4646 ToTU, classTemplateDecl(hasName("X")));
4647 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4648 ToTU,
4649 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4650
4651 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4652 ToTU, classTemplateSpecializationDecl(hasName("X")));
4653 FieldDecl *FieldInSpec = *Spec->field_begin();
4654 ASSERT_TRUE(FieldInSpec);
4655
4656 DeclarationName Name = FieldInSpec->getDeclName();
4657 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4658
4659 SmallVector<NamedDecl *, 2> FoundDecls;
4660 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4661 EXPECT_EQ(FoundDecls.size(), 1u);
4662 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4663
4664 auto Res = LT.lookup(TemplateDC, Name);
4665 ASSERT_EQ(Res.size(), 1u);
4666 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4667
4668 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4669 FoundDecls);
4670 EXPECT_EQ(FoundDecls.size(), 1u);
4671 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4672
4673 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4674 ASSERT_EQ(Res.size(), 1u);
4675 EXPECT_EQ(*Res.begin(), FieldInSpec);
4676}
4677
4678TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4679 TranslationUnitDecl *ToTU = getToTuDecl(
4680 R"(
4681 class Y { template <class T> friend void F(); };
4682 )",
4683 Lang_CXX03);
4684
4685 ASTImporterLookupTable LT(*ToTU);
4686 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4687 ToTU, functionTemplateDecl(hasName("F")));
4688 DeclarationName Name = F->getDeclName();
4689 auto Res = LT.lookup(ToTU, Name);
4690 EXPECT_EQ(Res.size(), 2u);
4691 EXPECT_EQ(Res.count(F), 1u);
4692 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4693}
4694
4695TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4696 TranslationUnitDecl *ToTU = getToTuDecl(
4697 R"(
4698 struct X;
4699 struct A {
4700 friend struct X;
4701 };
4702 struct B {
4703 friend struct X;
4704 };
4705 )",
4706 Lang_CXX03);
4707
4708 ASTImporterLookupTable LT(*ToTU);
4709 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4710 ToTU, cxxRecordDecl(hasName("X")));
4711 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4712 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4713 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4714 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4715 ASSERT_EQ(RD0, RD1);
4716 ASSERT_EQ(RD1, X);
4717
4718 DeclarationName Name = X->getDeclName();
4719 auto Res = LT.lookup(ToTU, Name);
4720 EXPECT_EQ(Res.size(), 1u);
4721 EXPECT_EQ(*Res.begin(), X);
4722}
4723
4724TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4725 TranslationUnitDecl *ToTU = getToTuDecl(
4726 R"(
4727 enum E {
4728 A,
4729 B
4730 };
4731 )",
4732 Lang_C99);
4733
4734 ASTImporterLookupTable LT(*ToTU);
4735 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4736 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4737 ToTU, enumConstantDecl(hasName("A")));
4738
4739 DeclarationName Name = A->getDeclName();
4740 // Redecl context is the TU.
4741 ASSERT_EQ(E->getRedeclContext(), ToTU);
4742
4743 SmallVector<NamedDecl *, 2> FoundDecls;
4744 // Normal lookup finds in the DC.
4745 E->localUncachedLookup(Name, FoundDecls);
4746 EXPECT_EQ(FoundDecls.size(), 1u);
4747
4748 // Normal lookup finds in the Redecl context.
4749 ToTU->localUncachedLookup(Name, FoundDecls);
4750 EXPECT_EQ(FoundDecls.size(), 1u);
4751
4752 // Import specific lookup finds in the DC.
4753 auto Res = LT.lookup(E, Name);
4754 ASSERT_EQ(Res.size(), 1u);
4755 EXPECT_EQ(*Res.begin(), A);
4756
4757 // Import specific lookup finds in the Redecl context.
4758 Res = LT.lookup(ToTU, Name);
4759 ASSERT_EQ(Res.size(), 1u);
4760 EXPECT_EQ(*Res.begin(), A);
4761}
4762
4763TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4764 TranslationUnitDecl *ToTU = getToTuDecl(
4765 R"(
4766 namespace N {
4767 int A;
4768 }
4769 namespace N {
4770 }
4771 )",
4772 Lang_CXX03);
4773 auto *N1 =
4774 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4775 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4776 DeclarationName Name = A->getDeclName();
4777
4778 ASTImporterLookupTable LT(*ToTU);
4779 auto Res = LT.lookup(N1, Name);
4780 ASSERT_EQ(Res.size(), 1u);
4781 EXPECT_EQ(*Res.begin(), A);
4782}
4783
4784TEST_P(ASTImporterOptionSpecificTestBase,
4785 RedeclChainShouldBeCorrectAmongstNamespaces) {
4786 Decl *FromTU = getTuDecl(
4787 R"(
4788 namespace NS {
4789 struct X;
4790 struct Y {
4791 static const int I = 3;
4792 };
4793 }
4794 namespace NS {
4795 struct X { // <--- To be imported
4796 void method(int i = Y::I) {}
4797 int f;
4798 };
4799 }
4800 )",
4801 Lang_CXX03);
4802 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
4803 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
4804 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
4805 FromTU,
4806 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
4807 ASSERT_NE(FromFwd, FromDef);
4808 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
4809 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4810 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
4811
4812 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX03));
4813 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX03));
4814 EXPECT_NE(ToFwd, ToDef);
4815 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
4816 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4817 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
4818 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4819 // We expect no (ODR) warning during the import.
4820 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4821}
4822
4823struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
4824
4825TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
4826 Decl *ToTU = getToTuDecl(
4827 R"(
4828 class X {
4829 template <typename T> friend void foo();
4830 };
4831 )",
4832 Lang_CXX03);
4833 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
4834 ToTU, functionTemplateDecl(hasName("foo")));
4835
4836 Decl *FromTU = getTuDecl(
4837 R"(
4838 template <typename T> void foo();
4839 )",
4840 Lang_CXX03);
4841 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
4842 FromTU, functionTemplateDecl(hasName("foo")));
4843 auto *Imported = Import(FromFoo, Lang_CXX03);
4844
4845 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
4846}
4847
4848struct ASTImporterWithFakeErrors : ASTImporter {
4849 using ASTImporter::ASTImporter;
4850 bool returnWithErrorInTest() override { return true; }
4851};
4852
4853struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
4854 ErrorHandlingTest() {
4855 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
4856 ASTContext &FromContext, FileManager &FromFileManager,
4857 bool MinimalImport,
4858 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
4859 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
4860 FromContext, FromFileManager,
4861 MinimalImport, SharedState);
4862 };
4863 }
4864 // In this test we purposely report an error (UnsupportedConstruct) when
4865 // importing the below stmt.
4866 static constexpr auto* ErroneousStmt = R"( asm(""); )";
4867};
4868
4869// Check a case when no new AST node is created in the AST before encountering
4870// the error.
4871TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
4872 TranslationUnitDecl *ToTU = getToTuDecl(
4873 R"(
4874 template <typename T>
4875 class X {};
4876 template <>
4877 class X<int> { int a; };
4878 )",
4879 Lang_CXX03);
4880 TranslationUnitDecl *FromTU = getTuDecl(
4881 R"(
4882 template <typename T>
4883 class X {};
4884 template <>
4885 class X<int> { double b; };
4886 )",
4887 Lang_CXX03);
4888 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4889 FromTU, classTemplateSpecializationDecl(hasName("X")));
4890 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX03);
4891 EXPECT_FALSE(ImportedSpec);
4892
4893 // The original Decl is kept, no new decl is created.
4894 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
4895 ToTU, classTemplateSpecializationDecl(hasName("X"))),
4896 1u);
4897
4898 // But an error is set to the counterpart in the "from" context.
4899 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
4900 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec);
4901 ASSERT_TRUE(OptErr);
4902 EXPECT_EQ(OptErr->Error, ImportError::NameConflict);
4903}
4904
4905// Check a case when a new AST node is created but not linked to the AST before
4906// encountering the error.
4907TEST_P(ErrorHandlingTest,
4908 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
4909 TranslationUnitDecl *FromTU = getTuDecl(
4910 std::string("void foo() { ") + ErroneousStmt + " }", Lang_CXX03);
4911 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4912 FromTU, functionDecl(hasName("foo")));
4913
4914 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX03);
4915 EXPECT_FALSE(ImportedFoo);
4916
4917 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4918 // Created, but not linked.
4919 EXPECT_EQ(
4920 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
4921 0u);
4922
4923 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
4924 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo);
4925 ASSERT_TRUE(OptErr);
4926 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4927}
4928
4929// Check a case when a new AST node is created and linked to the AST before
4930// encountering the error. The error is set for the counterpart of the nodes in
4931// the "from" context.
4932TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
4933 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
4934 void f();
4935 void f() { )") + ErroneousStmt + R"( }
4936 )",
4937 Lang_CXX03);
4938 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
4939 FromTU, functionDecl(hasName("f")));
4940 auto *FromDef =
4941 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
4942 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX03);
4943 EXPECT_FALSE(ImportedProto); // Could not import.
4944 // However, we created two nodes in the AST. 1) the fwd decl 2) the
4945 // definition. The definition is not added to its DC, but the fwd decl is
4946 // there.
4947 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4948 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
4949 1u);
4950 // Match the fwd decl.
4951 auto *ToProto =
4952 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
4953 EXPECT_TRUE(ToProto);
4954 // An error is set to the counterpart in the "from" context both for the fwd
4955 // decl and the definition.
4956 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
4957 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto);
4958 ASSERT_TRUE(OptErr);
4959 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4960 OptErr = Importer->getImportDeclErrorIfAny(FromDef);
4961 ASSERT_TRUE(OptErr);
4962 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4963}
4964
4965// An error should be set for a class if we cannot import one member.
4966TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
4967 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
4968 class X {
4969 void f() { )") + ErroneousStmt + R"( } // This member has the error
4970 // during import.
4971 void ok(); // The error should not prevent importing this.
4972 }; // An error will be set for X too.
4973 )",
4974 Lang_CXX03);
4975 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
4976 FromTU, cxxRecordDecl(hasName("X")));
4977 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
4978
4979 // An error is set for X.
4980 EXPECT_FALSE(ImportedX);
4981 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
4982 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
4983 ASSERT_TRUE(OptErr);
4984 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4985
4986 // An error is set for f().
4987 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
4988 FromTU, cxxMethodDecl(hasName("f")));
4989 OptErr = Importer->getImportDeclErrorIfAny(FromF);
4990 ASSERT_TRUE(OptErr);
4991 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4992 // And any subsequent import should fail.
4993 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX03);
4994 EXPECT_FALSE(ImportedF);
4995
4996 // There is an error set for the other member too.
4997 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
4998 FromTU, cxxMethodDecl(hasName("ok")));
4999 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
5000 EXPECT_TRUE(OptErr);
5001 // Cannot import the other member.
5002 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX03);
5003 EXPECT_FALSE(ImportedOK);
5004}
5005
5006// Check that an error propagates to the dependent AST nodes.
5007// In the below code it means that an error in X should propagate to A.
5008// And even to F since the containing A is erroneous.
5009// And to all AST nodes which we visit during the import process which finally
5010// ends up in a failure (in the error() function).
5011TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
5012 Decl *FromTU = getTuDecl(std::string(R"(
5013 namespace NS {
5014 class A {
5015 template <int I> class F {};
5016 class X {
5017 template <int I> friend class F;
5018 void error() { )") +
5019 ErroneousStmt + R"( }
5020 };
5021 };
5022
5023 class B {};
5024 } // NS
5025 )",
5026 Lang_CXX03, "input0.cc");
5027
5028 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
5029 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
5030 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
5031 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
5032 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
5033 FromTU, cxxRecordDecl(hasName("B"), isDefinition()));
5034 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
5035 FromTU, namespaceDecl(hasName("NS")));
5036
5037 // Start by importing the templated CXXRecordDecl of F.
5038 // Import fails for that.
5039 EXPECT_FALSE(Import(FromFRD, Lang_CXX03));
5040 // Import fails for A.
5041 EXPECT_FALSE(Import(FromA, Lang_CXX03));
5042 // But we should be able to import the independent B.
5043 EXPECT_TRUE(Import(FromB, Lang_CXX03));
5044 // And the namespace.
5045 EXPECT_TRUE(Import(FromNS, Lang_CXX03));
5046
5047 // An error is set to the templated CXXRecordDecl of F.
5048 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get();
5049 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFRD);
5050 EXPECT_TRUE(OptErr);
5051
5052 // An error is set to A.
5053 OptErr = Importer->getImportDeclErrorIfAny(FromA);
5054 EXPECT_TRUE(OptErr);
5055
5056 // There is no error set to B.
5057 OptErr = Importer->getImportDeclErrorIfAny(FromB);
5058 EXPECT_FALSE(OptErr);
5059
5060 // There is no error set to NS.
5061 OptErr = Importer->getImportDeclErrorIfAny(FromNS);
5062 EXPECT_FALSE(OptErr);
5063
5064 // Check some of those decls whose ancestor is X, they all should have an
5065 // error set if we visited them during an import process which finally failed.
5066 // These decls are part of a cycle in an ImportPath.
5067 // There would not be any error set for these decls if we hadn't follow the
5068 // ImportPaths and the cycles.
5069 OptErr = Importer->getImportDeclErrorIfAny(
5070 FirstDeclMatcher<ClassTemplateDecl>().match(
5071 FromTU, classTemplateDecl(hasName("F"))));
5072 // An error is set to the 'F' ClassTemplateDecl.
5073 EXPECT_TRUE(OptErr);
5074 // An error is set to the FriendDecl.
5075 OptErr = Importer->getImportDeclErrorIfAny(
5076 FirstDeclMatcher<FriendDecl>().match(
5077 FromTU, friendDecl()));
5078 EXPECT_TRUE(OptErr);
5079 // An error is set to the implicit class of A.
5080 OptErr =
5081 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5082 FromTU, cxxRecordDecl(hasName("A"), isImplicit())));
5083 EXPECT_TRUE(OptErr);
5084 // An error is set to the implicit class of X.
5085 OptErr =
5086 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5087 FromTU, cxxRecordDecl(hasName("X"), isImplicit())));
5088 EXPECT_TRUE(OptErr);
5089}
5090
5091TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
5092 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5093 namespace X {
5094 void f() { )") + ErroneousStmt + R"( } // This member has the error
5095 // during import.
5096 void ok(); // The error should not prevent importing this.
5097 }; // An error will be set for X too.
5098 )",
5099 Lang_CXX03);
5100 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
5101 FromTU, namespaceDecl(hasName("X")));
5102 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX03);
5103
5104 // There is no error set for X.
5105 EXPECT_TRUE(ImportedX);
5106 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5107 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5108 ASSERT_FALSE(OptErr);
5109
5110 // An error is set for f().
5111 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
5112 FromTU, functionDecl(hasName("f")));
5113 OptErr = Importer->getImportDeclErrorIfAny(FromF);
5114 ASSERT_TRUE(OptErr);
5115 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5116 // And any subsequent import should fail.
5117 FunctionDecl *ImportedF = Import(FromF, Lang_CXX03);
5118 EXPECT_FALSE(ImportedF);
5119
5120 // There is no error set for ok().
5121 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
5122 FromTU, functionDecl(hasName("ok")));
5123 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
5124 EXPECT_FALSE(OptErr);
5125 // And we should be able to import.
5126 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX03);
5127 EXPECT_TRUE(ImportedOK);
5128}
5129
5130// An error should be set for a class if it had a previous import with an error
5131// from another TU.
5132TEST_P(ErrorHandlingTest,
5133 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {
5134 // We already have a fwd decl.
5135 TranslationUnitDecl *ToTU = getToTuDecl("class X;", Lang_CXX03);
5136 // Then we import a definition.
5137 {
5138 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5139 class X {
5140 void f() { )") + ErroneousStmt + R"( }
5141 void ok();
5142 };
5143 )",
5144 Lang_CXX03);
5145 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5146 FromTU, cxxRecordDecl(hasName("X")));
5147 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
5148
5149 // An error is set for X ...
5150 EXPECT_FALSE(ImportedX);
5151 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5152 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5153 ASSERT_TRUE(OptErr);
5154 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5155 }
5156 // ... but the node had been created.
5157 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(
5158 ToTU, cxxRecordDecl(hasName("X"), isDefinition()));
5159 // An error is set for "ToXDef" in the shared state.
5160 Optional<ImportError> OptErr =
5161 SharedStatePtr->getImportDeclErrorIfAny(ToXDef);
5162 ASSERT_TRUE(OptErr);
5163 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5164
5165 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5166 ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition())));
5167 // An error is NOT set for the fwd Decl of X in the shared state.
5168 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXFwd);
5169 ASSERT_FALSE(OptErr);
5170
5171 // Try to import X again but from another TU.
5172 {
5173 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5174 class X {
5175 void f() { )") + ErroneousStmt + R"( }
5176 void ok();
5177 };
5178 )",
5179 Lang_CXX03, "input1.cc");
5180
5181 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5182 FromTU, cxxRecordDecl(hasName("X")));
5183 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
5184
5185 // If we did not save the errors for the "to" context then the below checks
5186 // would fail, because the lookup finds the fwd Decl of the existing
5187 // definition in the "to" context. We can reach the existing definition via
5188 // the found fwd Decl. That existing definition is structurally equivalent
5189 // (we check only the fields) with this one we want to import, so we return
5190 // with the existing definition, which is erroneous (one method is missing).
5191
5192 // The import should fail.
5193 EXPECT_FALSE(ImportedX);
5194 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5195 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5196 // And an error is set for this new X in the "from" ctx.
5197 ASSERT_TRUE(OptErr);
5198 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5199 }
5200}
5201
5202TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) {
5203 auto MatchFooA =
5204 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("A"))));
5205 auto MatchFooB =
5206 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("B"))));
5207 auto MatchFooC =
5208 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("C"))));
5209
5210 // Provoke import of a method that has overridden methods with import error.
5211 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5212 struct C;
5213 struct A {
5214 virtual void foo();
5215 void f1(C *);
5216 };
5217 void A::foo() {
5218 )") + ErroneousStmt + R"(
5219 }
5220 struct B : public A {
5221 void foo() override;
5222 };
5223 struct C : public B {
5224 void foo() override;
5225 };
5226 )",
5227 Lang_CXX11);
5228 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA);
5229 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB);
5230 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC);
5231
5232 EXPECT_FALSE(Import(FromFooA, Lang_CXX11));
5233 ASTImporter *Importer = findFromTU(FromFooA)->Importer.get();
5234 auto CheckError = [&Importer](Decl *FromD) {
5235 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromD);
5236 ASSERT_TRUE(OptErr);
5237 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5238 };
5239 CheckError(FromFooA);
5240 EXPECT_FALSE(Import(FromFooB, Lang_CXX11));
5241 CheckError(FromFooB);
5242 EXPECT_FALSE(Import(FromFooC, Lang_CXX11));
5243 CheckError(FromFooC);
5244}
5245
5246TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
5247 Decl *FromTU = getTuDecl(
5248 R"(
5249 void f() {
5250 auto L = [](){};
5251 }
5252 )",
5253 Lang_CXX11, "input0.cc");
5254 auto Pattern = lambdaExpr();
5255 CXXRecordDecl *FromL =
5256 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5257
5258 auto ToL = Import(FromL, Lang_CXX11);
5259 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5260 unsigned FromLSize =
5261 std::distance(FromL->decls().begin(), FromL->decls().end());
5262 EXPECT_NE(ToLSize, 0u);
5263 EXPECT_EQ(ToLSize, FromLSize);
5264}
5265
5266TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
5267 Decl *FromTU = getTuDecl(
5268 R"(
5269 template <typename F>
5270 void f(F L = [](){}) {}
5271 )",
5272 Lang_CXX11, "input0.cc");
5273 auto Pattern = lambdaExpr();
5274 CXXRecordDecl *FromL =
5275 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5276
5277 auto ToL = Import(FromL, Lang_CXX11);
5278 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5279 unsigned FromLSize =
5280 std::distance(FromL->decls().begin(), FromL->decls().end());
5281 EXPECT_NE(ToLSize, 0u);
5282 EXPECT_EQ(ToLSize, FromLSize);
5283}
5284
5285TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {
5286 Decl *FromTU = getTuDecl(
5287 R"(
5288 auto l1 = [](unsigned lp) { return 1; };
5289 auto l2 = [](int lp) { return 2; };
5290 int f(int p) {
5291 return l1(p) + l2(p);
5292 }
5293 )",
5294 Lang_CXX11, "input0.cc");
5295 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
5296 FromTU, functionDecl(hasName("f")));
5297 FunctionDecl *ToF = Import(FromF, Lang_CXX11);
5298 EXPECT_TRUE(ToF);
5299}
5300
5301TEST_P(ASTImporterOptionSpecificTestBase,
5302 ImportExistingFriendClassTemplateDef) {
5303 auto Code =
5304 R"(
5305 template <class T1, class T2>
5306 struct Base {
5307 template <class U1, class U2>
5308 friend struct Class;
5309 };
5310 template <class T1, class T2>
5311 struct Class { };
5312 )";
5313
5314 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);
5315 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX03, "input.cc");
5316
5317 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5318 ToTU, classTemplateDecl(hasName("Class")));
5319 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5320 ToTU, classTemplateDecl(hasName("Class")));
5321 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
5322 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
5323 // Previous friend decl is not linked to it!
5324 ASSERT_FALSE(ToClassDef->getPreviousDecl());
5325 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
5326 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
5327
5328 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5329 FromTU, classTemplateDecl(hasName("Class")));
5330 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5331 FromTU, classTemplateDecl(hasName("Class")));
5332 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());
5333 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());
5334 ASSERT_FALSE(FromClassDef->getPreviousDecl());
5335 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);
5336 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);
5337
5338 auto *ImportedDef = Import(FromClassDef, Lang_CXX03);
5339 // At import we should find the definition for 'Class' even if the
5340 // prototype (inside 'friend') for it comes first in the AST and is not
5341 // linked to the definition.
5342 EXPECT_EQ(ImportedDef, ToClassDef);
5343}
5344
5345struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
5346 LLDBLookupTest() {
5347 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
5348 ASTContext &FromContext, FileManager &FromFileManager,
5349 bool MinimalImport,
5350 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
5351 return new ASTImporter(ToContext, ToFileManager, FromContext,
5352 FromFileManager, MinimalImport,
5353 // We use the regular lookup.
5354 /*SharedState=*/nullptr);
5355 };
5356 }
5357};
5358
5359TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
5360 TranslationUnitDecl *ToTU = getToTuDecl(
5361 R"(
5362 extern "C" {
5363 class X{};
5364 };
5365 )",
5366 Lang_CXX03);
5367 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
5368 ToTU, cxxRecordDecl(hasName("X")));
5369
5370 // Set up a stub external storage.
5371 ToTU->setHasExternalLexicalStorage(true);
5372 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
5373 ToTU->setMustBuildLookupTable();
5374 struct TestExternalASTSource : ExternalASTSource {};
5375 ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
5376
5377 Decl *FromTU = getTuDecl(
5378 R"(
5379 class X;
5380 )",
5381 Lang_CXX03);
5382 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5383 FromTU, cxxRecordDecl(hasName("X")));
5384 auto *ImportedX = Import(FromX, Lang_CXX03);
5385 // The lookup must find the existing class definition in the LinkageSpecDecl.
5386 // Then the importer renders the existing and the new decl into one chain.
5387 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
5388}
5389
5390struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
5391
5392TEST_P(SVEBuiltins, ImportTypes) {
5393 static const char *const TypeNames[] = {
5394 "__SVInt8_t",
5395 "__SVInt16_t",
5396 "__SVInt32_t",
5397 "__SVInt64_t",
5398 "__SVUint8_t",
5399 "__SVUint16_t",
5400 "__SVUint32_t",
5401 "__SVUint64_t",
5402 "__SVFloat16_t",
5403 "__SVBFloat16_t",
5404 "__SVFloat32_t",
5405 "__SVFloat64_t",
5406 "__SVBool_t"
5407 };
5408
5409 TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX03);
5410 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX03, "input.cc");
5411 for (auto *TypeName : TypeNames) {
5412 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
5413 ToTU, typedefDecl(hasName(TypeName)));
5414 QualType ToType = ToTypedef->getUnderlyingType();
5415
5416 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
5417 FromTU, typedefDecl(hasName(TypeName)));
5418 QualType FromType = FromTypedef->getUnderlyingType();
5419
5420 QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX03);
5421 EXPECT_EQ(ImportedType, ToType);
5422 }
5423}
5424
5425TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {
5426 // Test that import of implicit functions works and the functions
5427 // are merged into one chain.
5428 auto GetDeclToImport = [this](StringRef File) {
5429 Decl *FromTU = getTuDecl(
5430 R"(
5431 struct X { };
5432 // Force generating some implicit operator definitions for X.
5433 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }
5434 )",
5435 Lang_CXX11, File);
5436 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
5437 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5438 // Destructor is picked as one example of implicit function.
5439 return FromD->getDestructor();
5440 };
5441
5442 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11);
5443 ASSERT_TRUE(ToD1);
5444
5445 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11);
5446 ASSERT_TRUE(ToD2);
5447
5448 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());
5449}
5450
5451TEST_P(ASTImporterOptionSpecificTestBase,
5452 ImportOfExplicitlyDefaultedOrDeleted) {
5453 Decl *FromTU = getTuDecl(
5454 R"(
5455 struct X { X() = default; X(const X&) = delete; };
5456 )",
5457 Lang_CXX11);
5458 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5459 FromTU, cxxRecordDecl(hasName("X")));
5460 auto *ImportedX = Import(FromX, Lang_CXX11);
5461 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(
5462 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5463 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(
5464 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5465
5466 ASSERT_TRUE(ImportedX);
5467 EXPECT_TRUE(Constr1->isDefaulted());
5468 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());
5469 EXPECT_TRUE(Constr2->isDeletedAsWritten());
5470 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
5471}
5472
5473INSTANTIATE_TEST_CASE_P(ParameterizedTests, SVEBuiltins,
5474 ::testing::Values(std::vector<std::string>{
5475 "-target", "aarch64-linux-gnu"}), );
5476
5477INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5478 ::testing::Values(std::vector<std::string>()), );
5479
5480INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
5481 ::testing::Values(std::vector<std::string>()), );
5482
5483TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) {
5484 Decl *FromTU = getTuDecl(
5485 R"(
5486 void f() {
5487 auto L0 = [](){};
5488 auto L1 = [](){};
5489 }
5490 )",
5491 Lang_CXX11, "input0.cc");
5492 auto Pattern = lambdaExpr();
5493 CXXRecordDecl *FromL0 =
5494 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5495 CXXRecordDecl *FromL1 =
5496 LastDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5497 ASSERT_NE(FromL0, FromL1);
5498
5499 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5500 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5501 EXPECT_NE(ToL0, ToL1);
5502}
5503
5504TEST_P(ASTImporterOptionSpecificTestBase,
5505 LambdasInFunctionParamsAreDifferentiated) {
5506 Decl *FromTU = getTuDecl(
5507 R"(
5508 template <typename F0, typename F1>
5509 void f(F0 L0 = [](){}, F1 L1 = [](){}) {}
5510 )",
5511 Lang_CXX11, "input0.cc");
5512 auto Pattern = cxxRecordDecl(isLambda());
5513 CXXRecordDecl *FromL0 =
5514 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5515 CXXRecordDecl *FromL1 =
5516 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5517 ASSERT_NE(FromL0, FromL1);
5518
5519 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5520 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5521 ASSERT_NE(ToL0, ToL1);
5522}
5523
5524TEST_P(ASTImporterOptionSpecificTestBase,
5525 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) {
5526 Decl *FromTU = getTuDecl(
5527 R"(
5528 #define LAMBDA [](){}
5529 template <typename F0, typename F1>
5530 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {}
5531 )",
5532 Lang_CXX11, "input0.cc");
5533 auto Pattern = cxxRecordDecl(isLambda());
5534 CXXRecordDecl *FromL0 =
5535 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5536 CXXRecordDecl *FromL1 =
5537 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5538 ASSERT_NE(FromL0, FromL1);
5539
5540 Import(FromL0, Lang_CXX11);
5541 Import(FromL1, Lang_CXX11);
5542 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5543 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5544 ASSERT_NE(ToL0, ToL1);
5545}
5546
5547TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) {
5548 Decl *FromTU = getTuDecl(
5549 R"(
5550 void f() {
5551 auto x = []{} = {}; auto x2 = x;
5552 }
5553 )",
5554 Lang_CXX20, "input0.cc");
5555 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5556 FromTU, functionDecl(hasName("f")));
5557 // We have only one lambda class.
5558 ASSERT_EQ(
5559 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5560 1u);
5561
5562 FunctionDecl *ToF = Import(FromF, Lang_CXX20);
5563 EXPECT_TRUE(ToF);
5564 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5565 // We have only one lambda class after the import.
5566 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5567 1u);
5568}
5569
5570TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {
5571 Decl *FromTU = getTuDecl(
5572 R"(
5573 void f() {
5574 auto x = []{} = {};
5575 auto xb = []{} = {};
5576 }
5577 )",
5578 Lang_CXX20, "input0.cc");
5579 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5580 FromTU, functionDecl(hasName("f")));
5581 // We have two lambda classes.
5582 ASSERT_EQ(
5583 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5584 2u);
5585
5586 FunctionDecl *ToF = Import(FromF, Lang_CXX20);
5587 EXPECT_TRUE(ToF);
5588 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5589 // We have two lambda classes after the import.
5590 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5591 2u);
5592}
5593
5594TEST_P(ASTImporterOptionSpecificTestBase, ImplicitlyDeclareSelf) {
5595 Decl *FromTU = getTuDecl(R"(
5596 __attribute__((objc_root_class))
5597 @interface Root
5598 @end
5599 @interface C : Root
5600 -(void)method;
5601 @end
5602 @implementation C
5603 -(void)method {}
5604 @end
5605 )",
5606 Lang_OBJCXX, "input.mm");
5607 auto *FromMethod = LastDeclMatcher<ObjCMethodDecl>().match(
5608 FromTU, namedDecl(hasName("method")));
5609 ASSERT_TRUE(FromMethod);
5610 auto ToMethod = Import(FromMethod, Lang_OBJCXX);
5611 ASSERT_TRUE(ToMethod);
5612
5613 // Both methods should have their implicit parameters.
5614 EXPECT_TRUE(FromMethod->getSelfDecl() != nullptr);
5615 EXPECT_TRUE(ToMethod->getSelfDecl() != nullptr);
5616}
5617
5618struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {};
5619
5620TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {
5621 Decl *FromTU = getTuDecl(
5622 R"(
5623 auto X = [](long l) {
5624 using int_type = long;
5625 auto dur = 13;
5626 return static_cast<int_type>(dur);
5627 };
5628 )",
5629 Lang_CXX14, "input0.cc");
5630 CXXMethodDecl *From =
5631 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, cxxMethodDecl());
5632
5633 // Explicitly set the return type of the lambda's operator() to the TypeAlias.
5634 // Normally the return type would be the built-in 'long' type. However, there
5635 // are cases when Clang does not use the canonical type and the TypeAlias is
5636 // used. I could not create such an AST from regular source code, it requires
5637 // some special state in the preprocessor. I've found such an AST when Clang
5638 // parsed libcxx/src/filesystem/directory_iterator.cpp, but could not reduce
5639 // that with creduce, because after preprocessing, the AST no longer
5640 // contained the TypeAlias as a return type of the lambda.
5641 ASTContext &Ctx = From->getASTContext();
5642 TypeAliasDecl *FromTA =
5643 FirstDeclMatcher<TypeAliasDecl>().match(FromTU, typeAliasDecl());
5644 QualType TT = Ctx.getTypedefType(FromTA);
5645 const FunctionProtoType *FPT = cast<FunctionProtoType>(From->getType());
5646 QualType NewFunType =
5647 Ctx.getFunctionType(TT, FPT->getParamTypes(), FPT->getExtProtoInfo());
5648 From->setType(NewFunType);
5649
5650 CXXMethodDecl *To = Import(From, Lang_CXX14);
5651 EXPECT_TRUE(To);
5652 EXPECT_TRUE(isa<TypedefType>(To->getReturnType()));
5653}
5654
5655TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside) {
5656 Decl *FromTU = getTuDecl(
5657 R"(
5658 auto foo() {
5659 struct X {};
5660 return X();
5661 }
5662 )",
5663 Lang_CXX14, "input0.cc");
5664 FunctionDecl *From =
5665 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5666
5667 FunctionDecl *To = Import(From, Lang_CXX14);
5668 EXPECT_TRUE(To);
5669 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5670}
5671
5672TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside2) {
5673 Decl *FromTU = getTuDecl(
5674 R"(
5675 auto foo() {
5676 struct X {};
5677 return X();
5678 }
5679 )",
5680 Lang_CXX14, "input0.cc");
5681 FunctionDecl *From =
5682 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5683
5684 // This time import the type directly.
5685 QualType ToT = ImportType(From->getType(), From, Lang_CXX14);
5686 const FunctionProtoType *FPT = cast<FunctionProtoType>(ToT);
5687 EXPECT_TRUE(isa<AutoType>(FPT->getReturnType()));
5688}
5689
5690TEST_P(ImportAutoFunctions, ReturnWithTypedefToStructDeclaredInside) {
5691 Decl *FromTU = getTuDecl(
5692 R"(
5693 auto foo() {
5694 struct X {};
5695 using Y = X;
5696 return Y();
5697 }
5698 )",
5699 Lang_CXX14, "input0.cc");
5700 FunctionDecl *From =
5701 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5702
5703 FunctionDecl *To = Import(From, Lang_CXX14);
5704 EXPECT_TRUE(To);
5705 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5706}
5707
5708TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredNestedInside) {
5709 Decl *FromTU = getTuDecl(
5710 R"(
5711 auto foo() {
5712 struct X { struct Y{}; };
5713 return X::Y();
5714 }
5715 )",
5716 Lang_CXX14, "input0.cc");
5717 FunctionDecl *From =
5718 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5719
5720 FunctionDecl *To = Import(From, Lang_CXX14);
5721 EXPECT_TRUE(To);
5722 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5723}
5724
5725TEST_P(ImportAutoFunctions, ReturnWithInternalLambdaType) {
5726 Decl *FromTU = getTuDecl(
5727 R"(
5728 auto f() {
5729 auto l = []() {
5730 struct X {};
5731 return X();
5732 };
5733 return l();
5734 }
5735 )",
5736 Lang_CXX17, "input0.cc");
5737 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5738 FromTU, functionDecl(hasName("f")));
5739
5740 FunctionDecl *To = Import(From, Lang_CXX17);
5741 EXPECT_TRUE(To);
5742 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5743}
5744
5745TEST_P(ImportAutoFunctions, ReturnWithTypeInIf) {
5746 Decl *FromTU = getTuDecl(
5747 R"(
5748 auto f() {
5749 if (struct X {} x; true)
5750 return X();
5751 else
5752 return X();
5753 }
5754 )",
5755 Lang_CXX17, "input0.cc");
5756 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5757 FromTU, functionDecl(hasName("f")));
5758
5759 FunctionDecl *To = Import(From, Lang_CXX17);
5760 EXPECT_TRUE(To);
5761 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5762}
5763
5764TEST_P(ImportAutoFunctions, ReturnWithTypeInFor) {
5765 Decl *FromTU = getTuDecl(
5766 R"(
5767 auto f() {
5768 for (struct X {} x;;)
5769 return X();
5770 }
5771 )",
5772 Lang_CXX17, "input0.cc");
5773 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5774 FromTU, functionDecl(hasName("f")));
5775
5776 FunctionDecl *To = Import(From, Lang_CXX17);
5777 EXPECT_TRUE(To);
5778 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5779}
5780
5781TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {
5782 Decl *FromTU = getTuDecl(
5783 R"(
5784 auto f() {
5785 switch (struct X {} x; 10) {
5786 case 10:
5787 return X();
5788 }
5789 }
5790 )",
5791 Lang_CXX17, "input0.cc");
5792 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5793 FromTU, functionDecl(hasName("f")));
5794
5795 FunctionDecl *To = Import(From, Lang_CXX17);
5796 EXPECT_TRUE(To);
5797 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5798}
5799
5800struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {};
5801
5802TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) {
5803 // Tests that the FileID tree structure (with the links being the include
5804 // chains) is preserved while importing other files (which need to be
5805 // added to this structure with fake include locations.
5806
5807 SourceLocation Location1;
5808 {
5809 auto Pattern = varDecl(hasName("X"));
5810 Decl *FromTU = getTuDecl("int X;", Lang_C99, "input0.c");
5811 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5812
5813 Location1 = Import(FromD, Lang_C99)->getLocation();
5814 }
5815 SourceLocation Location2;
5816 {
5817 auto Pattern = varDecl(hasName("Y"));
5818 Decl *FromTU = getTuDecl("int Y;", Lang_C99, "input1.c");
5819 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5820
5821 Location2 = Import(FromD, Lang_C99)->getLocation();
5822 }
5823
5824 SourceManager &ToSM = ToAST->getSourceManager();
5825 FileID FileID1 = ToSM.getFileID(Location1);
5826 FileID FileID2 = ToSM.getFileID(Location2);
5827
5828 // Check that the imported files look like as if they were included from the
5829 // start of the main file.
5830 SourceLocation FileStart = ToSM.getLocForStartOfFile(ToSM.getMainFileID());
5831 EXPECT_NE(FileID1, ToSM.getMainFileID());
5832 EXPECT_NE(FileID2, ToSM.getMainFileID());
5833 EXPECT_EQ(ToSM.getIncludeLoc(FileID1), FileStart);
5834 EXPECT_EQ(ToSM.getIncludeLoc(FileID2), FileStart);
5835
5836 // Let the SourceManager check the order of the locations. The order should
5837 // be the order in which the declarations are imported.
5838 EXPECT_TRUE(ToSM.isBeforeInTranslationUnit(Location1, Location2));
5839 EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1));
5840}
5841
5842TEST_P(ImportSourceLocations, NormalFileBuffer) {
5843 // Test importing normal file buffers.
5844
5845 std::string Path = "input0.c";
5846 std::string Source = "int X;";
5847 TranslationUnitDecl *FromTU = getTuDecl(Source, Lang_C99, Path);
5848
5849 SourceLocation ImportedLoc;
5850 {
5851 // Import the VarDecl to trigger the importing of the FileID.
5852 auto Pattern = varDecl(hasName("X"));
5853 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5854 ImportedLoc = Import(FromD, Lang_C99)->getLocation();
5855 }
5856
5857 // Make sure the imported buffer has the original contents.
5858 SourceManager &ToSM = ToAST->getSourceManager();
5859 FileID ImportedID = ToSM.getFileID(ImportedLoc);
5860 EXPECT_EQ(Source,
5861 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
5862}
5863
5864TEST_P(ImportSourceLocations, OverwrittenFileBuffer) {
5865 // Test importing overwritten file buffers.
5866
5867 std::string Path = "input0.c";
5868 TranslationUnitDecl *FromTU = getTuDecl("int X;", Lang_C99, Path);
5869
5870 // Overwrite the file buffer for our input file with new content.
5871 const std::string Contents = "overwritten contents";
5872 SourceLocation ImportedLoc;
5873 {
5874 SourceManager &FromSM = FromTU->getASTContext().getSourceManager();
5875 clang::FileManager &FM = FromSM.getFileManager();
5876 const clang::FileEntry &FE =
5877 *FM.getVirtualFile(Path, static_cast<off_t>(Contents.size()), 0);
5878
5879 llvm::SmallVector<char, 64> Buffer;
5880 Buffer.append(Contents.begin(), Contents.end());
5881 auto FileContents =
5882 std::make_unique<llvm::SmallVectorMemoryBuffer>(std::move(Buffer), Path);
5883 FromSM.overrideFileContents(&FE, std::move(FileContents));
5884
5885 // Import the VarDecl to trigger the importing of the FileID.
5886 auto Pattern = varDecl(hasName("X"));
5887 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5888 ImportedLoc = Import(FromD, Lang_C99)->getLocation();
5889 }
5890
5891 // Make sure the imported buffer has the overwritten contents.
5892 SourceManager &ToSM = ToAST->getSourceManager();
5893 FileID ImportedID = ToSM.getFileID(ImportedLoc);
5894 EXPECT_EQ(Contents,
5895 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
5896}
5897
5898TEST_P(ASTImporterOptionSpecificTestBase, ImportExprOfAlignmentAttr) {
5899 // Test if import of these packed and aligned attributes does not trigger an
5900 // error situation where source location from 'From' context is referenced in
5901 // 'To' context through evaluation of the alignof attribute.
5902 // This happens if the 'alignof(A)' expression is not imported correctly.
5903 Decl *FromTU = getTuDecl(
5904 R"(
5905 struct __attribute__((packed)) A { int __attribute__((aligned(8))) X; };
5906 struct alignas(alignof(A)) S {};
5907 )",
5908 Lang_CXX11, "input.cc");
5909 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
5910 FromTU, cxxRecordDecl(hasName("S"), unless(isImplicit())));
5911 ASSERT_TRUE(FromD);
5912
5913 auto *ToD = Import(FromD, Lang_CXX11);
5914 ASSERT_TRUE(ToD);
5915
5916 auto *FromAttr = FromD->getAttr<AlignedAttr>();
5917 auto *ToAttr = ToD->getAttr<AlignedAttr>();
5918 EXPECT_EQ(FromAttr->isInherited(), ToAttr->isInherited());
5919 EXPECT_EQ(FromAttr->isPackExpansion(), ToAttr->isPackExpansion());
5920 EXPECT_EQ(FromAttr->isImplicit(), ToAttr->isImplicit());
5921 EXPECT_EQ(FromAttr->getSyntax(), ToAttr->getSyntax());
5922 EXPECT_EQ(FromAttr->getSemanticSpelling(), ToAttr->getSemanticSpelling());
5923 EXPECT_TRUE(ToAttr->getAlignmentExpr());
5924
5925 auto *ToA = FirstDeclMatcher<CXXRecordDecl>().match(
5926 ToD->getTranslationUnitDecl(),
5927 cxxRecordDecl(hasName("A"), unless(isImplicit())));
5928 // Ensure that 'struct A' was imported (through reference from attribute of
5929 // 'S').
5930 EXPECT_TRUE(ToA);
5931}
5932
5933TEST_P(ASTImporterOptionSpecificTestBase, ImportFormatAttr) {
5934 Decl *FromTU = getTuDecl(
5935 R"(
5936 int foo(const char * fmt, ...)
5937 __attribute__ ((__format__ (__scanf__, 1, 2)));
5938 )",
5939 Lang_CXX03, "input.cc");
5940 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
5941 FromTU, functionDecl(hasName("foo")));
5942 ASSERT_TRUE(FromD);
5943
5944 auto *ToD = Import(FromD, Lang_CXX03);
5945 ASSERT_TRUE(ToD);
5946 ToD->dump(); // Should not crash!
5947
5948 auto *FromAttr = FromD->getAttr<FormatAttr>();
5949 auto *ToAttr = ToD->getAttr<FormatAttr>();
5950 EXPECT_EQ(FromAttr->isInherited(), ToAttr->isInherited());
5951 EXPECT_EQ(FromAttr->isPackExpansion(), ToAttr->isPackExpansion());
5952 EXPECT_EQ(FromAttr->isImplicit(), ToAttr->isImplicit());
5953 EXPECT_EQ(FromAttr->getSyntax(), ToAttr->getSyntax());
5954 EXPECT_EQ(FromAttr->getAttributeSpellingListIndex(),
5955 ToAttr->getAttributeSpellingListIndex());
5956 EXPECT_EQ(FromAttr->getType()->getName(), ToAttr->getType()->getName());
5957}
5958template <typename T>
5959auto ExtendWithOptions(const T &Values, const std::vector<std::string> &Args) {
5960 auto Copy = Values;
5961 for (std::vector<std::string> &ArgV : Copy) {
5962 for (const std::string &Arg : Args) {
5963 ArgV.push_back(Arg);
5964 }
5965 }
5966 return ::testing::ValuesIn(Copy);
5967}
5968
5969struct ImportWithExternalSource : ASTImporterOptionSpecificTestBase {
5970 ImportWithExternalSource() {
5971 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
5972 ASTContext &FromContext, FileManager &FromFileManager,
5973 bool MinimalImport,
5974 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
5975 return new ASTImporter(ToContext, ToFileManager, FromContext,
5976 FromFileManager, MinimalImport,
5977 // We use the regular lookup.
5978 /*SharedState=*/nullptr);
5979 };
5980 }
5981};
5982
5983/// An ExternalASTSource that keeps track of the tags is completed.
5984struct SourceWithCompletedTagList : clang::ExternalASTSource {
5985 std::vector<clang::TagDecl *> &CompletedTags;
5986 SourceWithCompletedTagList(std::vector<clang::TagDecl *> &CompletedTags)
5987 : CompletedTags(CompletedTags) {}
5988 void CompleteType(TagDecl *Tag) override {
5989 auto *Record = cast<CXXRecordDecl>(Tag);
5990 Record->startDefinition();
5991 Record->completeDefinition();
5992 CompletedTags.push_back(Tag);
5993 }
5994 using clang::ExternalASTSource::CompleteType;
5995};
5996
5997TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) {
5998 // Create an empty TU.
5999 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX03, "input.cpp");
6000
6001 // Create and add the test ExternalASTSource.
6002 std::vector<clang::TagDecl *> CompletedTags;
6003 IntrusiveRefCntPtr<ExternalASTSource> source =
6004 new SourceWithCompletedTagList(CompletedTags);
6005 clang::ASTContext &Context = FromTU->getASTContext();
6006 Context.setExternalSource(std::move(source));
6007
6008 // Create a dummy class by hand with external lexical storage.
6009 IdentifierInfo &Ident = Context.Idents.get("test_class");
6010 auto *Record = CXXRecordDecl::Create(
6011 Context, TTK_Class, FromTU, SourceLocation(), SourceLocation(), &Ident);
6012 Record->setHasExternalLexicalStorage();
6013 FromTU->addDecl(Record);
6014
6015 // Do a minimal import of the created class.
6016 EXPECT_EQ(0U, CompletedTags.size());
6017 Import(Record, Lang_CXX03);
6018 EXPECT_EQ(0U, CompletedTags.size());
6019
6020 // Import the definition of the created class.
6021 llvm::Error Err = findFromTU(Record)->Importer->ImportDefinition(Record);
6022 EXPECT_FALSE((bool)Err);
6023 consumeError(std::move(Err));
6024
6025 // Make sure the class was completed once.
6026 EXPECT_EQ(1U, CompletedTags.size());
6027 EXPECT_EQ(Record, CompletedTags.front());
6028}
6029
6030TEST_P(ImportFunctions, CTADImplicit) {
6031 Decl *FromTU = getTuDecl(
6032 R"(
6033 template <typename T> struct A {
6034 A(T);
6035 };
6036 A a{(int)0};
6037 )",
6038 Lang_CXX17, "input.cc");
6039 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
6040 FromTU,
6041 cxxDeductionGuideDecl(hasParameter(0, hasType(asString("A<T>")))));
6042 auto *ToD = Import(FromD, Lang_CXX17);
6043 ASSERT_TRUE(ToD);
6044 EXPECT_TRUE(ToD->isCopyDeductionCandidate());
6045 // Check that the deduced class template is also imported.
6046 EXPECT_TRUE(findFromTU(FromD)->Importer->GetAlreadyImportedOrNull(
6047 FromD->getDeducedTemplate()));
6048}
6049
6050TEST_P(ImportFunctions, CTADUserDefinedExplicit) {
6051 Decl *FromTU = getTuDecl(
6052 R"(
6053 template <typename T> struct A {
6054 A(T);
6055 };
6056 template <typename T> explicit A(T) -> A<float>;
6057 A a{(int)0}; // calls A<float>::A(float)
6058 )",
6059 Lang_CXX17, "input.cc");
6060 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
6061 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));
6062 // Not-implicit: i.e. not compiler-generated, user defined.
6063 ASSERT_FALSE(FromD->isImplicit());
6064 ASSERT_TRUE(FromD->isExplicit()); // Has the explicit keyword.
6065 auto *ToD = Import(FromD, Lang_CXX17);
6066 ASSERT_TRUE(ToD);
6067 EXPECT_FALSE(FromD->isImplicit());
6068 EXPECT_TRUE(ToD->isExplicit());
6069}
6070
6071TEST_P(ImportFunctions, CTADWithLocalTypedef) {
6072 Decl *TU = getTuDecl(
6073 R"(
6074 template <typename T> struct A {
6075 typedef T U;
6076 A(U);
6077 };
6078 A a{(int)0};
6079 )",
6080 Lang_CXX17, "input.cc");
6081 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
6082 TU, cxxDeductionGuideDecl());
6083 auto *ToD = Import(FromD, Lang_CXX17);
6084 ASSERT_TRUE(ToD);
6085}
6086
6087// FIXME Move these tests out of ASTImporterTest. For that we need to factor
6088// out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase
6089// into a new test Fixture. Then we should lift up this Fixture to its own
6090// implementation file and only then could we reuse the Fixture in other AST
6091// unitttests.
6092struct CTAD : ASTImporterOptionSpecificTestBase {};
6093
6094TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedef) {
6095 Decl *TU = getTuDecl(
6096 R"(
6097 typedef int U;
6098 template <typename T> struct A {
6099 A(U, T);
6100 };
6101 A a{(int)0, (int)0};
6102 )",
6103 Lang_CXX17, "input.cc");
6104 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
6105 TU, cxxDeductionGuideDecl());
6106 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
6107 TU, typedefNameDecl(hasName("U")));
6108 ParmVarDecl *Param = Guide->getParamDecl(0);
6109 // The type of the first param (which is a typedef) should match the typedef
6110 // in the global scope.
6111 EXPECT_EQ(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
6112}
6113
6114TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedefInParamPtr) {
6115 Decl *TU = getTuDecl(
6116 R"(
6117 typedef int U;
6118 template <typename T> struct A {
6119 A(U*, T);
6120 };
6121 A a{(int*)0, (int)0};
6122 )",
6123 Lang_CXX17, "input.cc");
6124 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
6125 TU, cxxDeductionGuideDecl());
6126 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
6127 TU, typedefNameDecl(hasName("U")));
6128 ParmVarDecl *Param = Guide->getParamDecl(0);
6129 EXPECT_EQ(Param->getType()
6130 ->getAs<PointerType>()
6131 ->getPointeeType()
6132 ->getAs<TypedefType>()
6133 ->getDecl(),
6134 Typedef);
6135}
6136
6137TEST_P(CTAD, DeductionGuideShouldCopyALocalTypedef) {
6138 Decl *TU = getTuDecl(
6139 R"(
6140 template <typename T> struct A {
6141 typedef T U;
6142 A(U, T);
6143 };
6144 A a{(int)0, (int)0};
6145 )",
6146 Lang_CXX17, "input.cc");
6147 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
6148 TU, cxxDeductionGuideDecl());
6149 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
6150 TU, typedefNameDecl(hasName("U")));
6151 ParmVarDecl *Param = Guide->getParamDecl(0);
6152 EXPECT_NE(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
6153}
6154
6155INSTANTIATE_TEST_CASE_P(ParameterizedTests, CTAD,
6156 DefaultTestValuesForRunOptions, );
6157
6158TEST_P(ASTImporterOptionSpecificTestBase, TypedefWithAttribute) {
6159 Decl *TU = getTuDecl(
6160 R"(
6161 namespace N {
6162 typedef int X __attribute__((annotate("A")));
6163 }
6164 )",
6165 Lang_CXX17, "input.cc");
6166 auto *FromD =
6167 FirstDeclMatcher<TypedefDecl>().match(TU, typedefDecl(hasName("X")));
6168 auto *ToD = Import(FromD, Lang_CXX17);
6169 ASSERT_TRUE(ToD);
6170 ASSERT_EQ(ToD->getAttrs().size(), 1U);
6171 auto *ToAttr = dyn_cast<AnnotateAttr>(ToD->getAttrs()[0]);
6172 ASSERT_TRUE(ToAttr);
6173 EXPECT_EQ(ToAttr->getAnnotation(), "A");
6174}
6175
6176TEST_P(ASTImporterOptionSpecificTestBase,
6177 ImportOfTemplatedDeclWhenPreviousDeclHasNoDescribedTemplateSet) {
6178 Decl *FromTU = getTuDecl(
6179 R"(
6180
6181 namespace std {
6182 template<typename T>
6183 class basic_stringbuf;
6184 }
6185 namespace std {
6186 class char_traits;
6187 template<typename T = char_traits>
6188 class basic_stringbuf;
6189 }
6190 namespace std {
6191 template<typename T>
6192 class basic_stringbuf {};
6193 }
6194
6195 )",
6196 Lang_CXX11);
6197
6198 auto *From1 = FirstDeclMatcher<ClassTemplateDecl>().match(
6199 FromTU,
6200 classTemplateDecl(hasName("basic_stringbuf"), unless(isImplicit())));
6201 auto *To1 = cast_or_null<ClassTemplateDecl>(Import(From1, Lang_CXX11));
6202 EXPECT_TRUE(To1);
6203
6204 auto *From2 = LastDeclMatcher<ClassTemplateDecl>().match(
6205 FromTU,
6206 classTemplateDecl(hasName("basic_stringbuf"), unless(isImplicit())));
6207 auto *To2 = cast_or_null<ClassTemplateDecl>(Import(From2, Lang_CXX11));
6208 EXPECT_TRUE(To2);
6209}
6210
6211INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
6212 DefaultTestValuesForRunOptions, );
6213
6214INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportPath,
6215 ::testing::Values(std::vector<std::string>()), );
6216
6217INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
6218 DefaultTestValuesForRunOptions, );
6219
6220INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFixedPointExpr,
6221 ExtendWithOptions(DefaultTestArrayForRunOptions,
6222 std::vector<std::string>{
6223 "-ffixed-point"}), );
6224
6225INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
6226 DefaultTestValuesForRunOptions, );
6227
6228INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
6229 DefaultTestValuesForRunOptions, );
6230
6231INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
6232 DefaultTestValuesForRunOptions, );
6233
6234INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
6235 DefaultTestValuesForRunOptions, );
6236
6237INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
6238 DefaultTestValuesForRunOptions, );
6239
6240INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
6241 DefaultTestValuesForRunOptions, );
6242
6243INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportAutoFunctions,
6244 DefaultTestValuesForRunOptions, );
6245
6246INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates,
6247 DefaultTestValuesForRunOptions, );
6248
6249INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
6250 DefaultTestValuesForRunOptions, );
6251
6252INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
6253 DefaultTestValuesForRunOptions, );
6254
6255INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
6256 DefaultTestValuesForRunOptions, );
6257
6258INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
6259 DefaultTestValuesForRunOptions, );
6260
6261INSTANTIATE_TEST_CASE_P(ParameterizedTests,
6262 ImportFunctionTemplateSpecializations,
6263 DefaultTestValuesForRunOptions, );
6264
6265INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
6266 DefaultTestValuesForRunOptions, );
6267
6268INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
6269 DefaultTestValuesForRunOptions, );
6270
6271INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
6272 DefaultTestValuesForRunOptions, );
6273
6274INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportSourceLocations,
6275 DefaultTestValuesForRunOptions, );
6276
6277INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportWithExternalSource,
6278 DefaultTestValuesForRunOptions, );
6279
6280} // end namespace ast_matchers
6281} // end namespace clang
6282